2016-11-17 9 views
1

は、私はそれは巨大なデータセットに適用されるように、この問題への最速-可能な解決策を必要としますリストのリスト:Pythonの比較トークン化リスト

r=[['abc','def'],['bcd','cde'],['abc','def','bcd']] 

rの各リストをマスターリスト(m)と比較してリストの新しいリストを生成したいと考えています。この新しいオブジェクトは、mの順序に基づいた一致の場合は1、不一致の場合は0になります。したがって、新しいオブジェクト(リストのリスト)は常にmと同じ長さのリストを持ちます。 Rの最初の要素は['abc','def']で、第一と一致 とメートルの第四の要素を持っているので

[[1,0,0,1],[0,1,1,0],[1,1,0,1]] 

、結果はその後、[1,0,0,1]です: は、ここで私は上記のMとrに基づいて期待するものです。

はここで、これまで私のアプローチです(おそらくあまりにも遅いとゼロが欠落している):

output=[] 
for i in r: 
    output.append([1 for x in m if x in i]) 

その結果:

[[1, 1], [1, 1], [1, 1, 1]] 

おかげで事前に! 1つのループでnp.in1dを使用して

答えて

3

あなたはこのようにネストされたリストの内包表記を使用することができます。

>>> m = ['abc','bcd','cde','def'] 
>>> r = [['abc','def'],['bcd','cde'],['abc','def','bcd']] 
>>> [[1 if mx in rx else 0 for mx in m] for rx in r] 
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]] 

また、あなたがint(...)を使用して1 if ... else 0を短縮することができ、あなたがrのサブリストに変換することができますmx in rxルックアップがより高速になるように、に設定してください。

>>> [[int(mx in rx) for mx in m] for rx in r] 
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]] 
>>> [[int(mx in rx) for mx in m] for rx in map(set, r)] 
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]] 

int(...)1 if ... else 0より少し短いですが、また、遅くなるようですので、あなたはおそらくそれを使用しないでください。繰り返し検索する前にrのサブリストをsetに変換すると、リストが長くなるほど処理が速くなりますが、非常に短いリストのサンプルでは、​​実際には単純なアプローチよりも遅いです。 setを使用して

長いリストでは
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in r] 
100000 loops, best of 3: 4.74 µs per loop 
>>> %timeit [[int(mx in rx) for mx in m] for rx in r] 
100000 loops, best of 3: 8.07 µs per loop 
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in map(set, r)] 
100000 loops, best of 3: 5.82 µs per loop 

は、予想されるように、速くなり:救助へ

>>> m = [random.randint(1, 100) for _ in range(50)] 
>>> r = [[random.randint(1,100) for _ in range(10)] for _ in range(20)] 
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in r] 
1000 loops, best of 3: 412 µs per loop 
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in map(set, r)] 
10000 loops, best of 3: 208 µs per loop 
1

一つのアプローチ -

out = np.empty((len(r),len(m)),dtype=int) 
for i,item in enumerate(r): 
    out[i] = np.in1d(m,item) 

私たちは、メモリとパフォーマンスのためにdtype=boolを使用することができます - 明示的なループで

np.array([np.in1d(m,i) for i in r]).astype(int) 

それは次のようになります。

サンプル実行 - rが等しい長さのリストを持っていた場合

In [18]: m 
Out[18]: ['abc', 'bcd', 'cde', 'def'] 

In [19]: r 
Out[19]: [['abc', 'def'], ['bcd', 'cde'], ['abc', 'def', 'bcd']] 

In [20]: np.array([np.in1d(m,i) for i in r]).astype(int) 
Out[20]: 
array([[1, 0, 0, 1], 
     [0, 1, 1, 0], 
     [1, 1, 0, 1]]) 

は、我々は完全にベクトル化されたアプローチを使用することもできました。

1

あなたはほとんどそこにいました。

あなたはそれがない場合はxm内のすべてのxため、i0である場合1を追加します。

だから、スクリプトはそれが聞こえるようになります。1 if x in i else 0for x in m、条件など:

[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]] 
1

output = [[1 if x in i else 0 for x in m] for i in r] 
print(output) 

結果をnumpyがなければ、あなたはネストされたリストの内包表記を使用してそれを行うことがとして:

>>> m = ['abc','bcd','cde','def'] 
>>> r = [['abc','def'],['bcd','cde'],['abc','def','bcd']] 

>>> [[int(mm in rr) for mm in m] for rr in r] 
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]] 

0Trueとして1と処理するので、実際にはタイプキャストはintにする必要はありません。また、boolの値を使用するとメモリ効率が向上します。したがって、あなたの式は次のようになります。

>>> [[mm in rr for mm in m] for rr in r] 
[[True, False, False, True], [False, True, True, False], [True, True, False, True]] 
0

マルチプロセッシング!

import multiprocessing as mp 

def matcher(qIn, qOut): 
    m = set(['abc','bcd','cde','def']) 
    for i,L in iter(qIn.get, None): 
     answer = [1 if e in m else 0 for e in L] 
     qOut.put((i,answer)) 


def main(L): 
    qIn, qOut = [mp.Queue() for _ in range(2)] 
    procs = [mp.Process(target=matcher, args=(qIn, qOut)) for _ in range(mp.cpu_count()-1)] 
    for p in procs: p.start() 

    numElems = len(L) 
    for t in enumerate(L): qIn.put(t) 
    for p in procs: qIn.put(None) 

    done = 0 
    while done < numElems: 
     i,answer = qIn.get() 
     L[i] = answer 
     done += 1 

    for p in procs: p.terminate() 

if __name__ == "__main__": 
    L = [['abc','def'],['bcd','cde'],['abc','def','bcd']] 
    main(L) 
    # now L looks like the required output