2016-07-20 1 views
1

私はNumpyとSciPyを使用しています。私は2つの配列を持っています。最初はバイナリで、2番目の配列はaからbまでの自然数の連続した範囲です。バイナリ配列の1を自然数で置き換えて、0の位置を維持するにはどうすればよいですか?

mask = np.array([1, 1, 1, 1, 0, 0, 1, 0]) # length of 8, with 5 ones and 3 zeros 
vals = np.array([2, 3, 4, 5, 6, 7, 8, 9]) # length of 8, only first 5 values will be used in this case - corresponding to the 5 ones in the first array 

私は本質的に、第1の配列の1を第2の配列の値と置き換えたいとします。私はすでにnumpyのマスクされた配列とvectorise機能を備えたさまざまな方法を試してみた

result = [2,3,4,5,0,0,6,0] 

:このシナリオ例のようになりますで必要な結果。私の現在の解決策は以下の通りですが、状態を維持するために、私はグローバル変数を導入しなければなりませんでした!

global count 
count = 0 
def func(a,b): 
    global count 
    if a ==1: 
     return b - count 
    else: 
     count +=1 
     return 0 
v_func = np.vectorize(func) 
result = v_func(mask, vals) 
print result 

(これは理想的にはNumPyを使用しています)これを行うもっとエレガントな方法がありますか?

(私が扱っている実際の配列は非常に大きいので、私の解決策は消費されるメモリの量に敏感である必要があります - 明らかに私は疎配列に変換できますが、 。別の解決策を見つけようと数回)

答えて

2

は、ここに1つの方法です。私はそれが最適化された方法と非常にエレガントではないではないと言わなければならないのにここ

In [15]: result = np.zeros_like(vals) 

In [16]: result[mask > 0] = vals[:mask.sum()] 

In [17]: result 
Out[17]: array([2, 3, 4, 5, 0, 0, 6, 0]) 
+0

ありがとうございますが、これは私が探しているものではありません。アイデアは、値が置き換えられたときにカウントを維持する(つまり、 'vals'配列の次の値のトラックを維持する)ため、ソリューションに '8'がある場合は '6'が必要です。これは 'vals'配列の次の値です。 – Mark

+0

@マーク投稿した直後に気付きました。今は修正されています。 –

+0

素晴らしい - ありがとう! – Mark

2

は、1つのライナーです。しかし、あなたは練習のためにそれを調べることができます。

a = [1, 1, 1, 1, 0, 0, 1, 0] 
b = [2, 3, 4, 5, 6, 7, 8, 9] 

c = [b[sum(a[:i])] if a[i] else 0 for i in range(len(a))] 
print c 
# Gives [2, 3, 4, 5, 0, 0, 6, 0] 
関連する問題