次の問題があります
次のような文を含むデータフレームmasterがあります
master
Out[8]:
original
0 this is a Nice sentence
1 this is another one
2 stackoverflow is Nice
マスターのすべての行について、fuzzywuzzy
を使用して別のデータフレームslaveを検索し、最も一致するものを探します。 2つのデータフレーム間で一致する文が少し異なる可能性があるため(余分な文字など)、私はfuzzywuzzyを使用します。
たとえば、slaveは
slave
Out[10]:
my_value name
0 2 hello world
1 1 congratulations
2 2 this is a Nice sentence
3 3 this is another one
4 1 stackoverflow is Nice
これは、完全に機能する、素晴らしい、コンパクトな作業例です:)
from fuzzywuzzy import fuzz
import pandas as pd
import numpy as np
import difflib
master= pd.DataFrame({'original':['this is a Nice sentence',
'this is another one',
'stackoverflow is Nice']})
slave= pd.DataFrame({'name':['hello world',
'congratulations',
'this is a Nice sentence ',
'this is another one',
'stackoverflow is Nice'],'my_value': [2,1,2,3,1]})
def fuzzy_score(str1, str2):
return fuzz.token_set_ratio(str1, str2)
def helper(orig_string, slave_df):
#use fuzzywuzzy to see how close original and name are
slave_df['score'] = slave_df.name.apply(lambda x: fuzzy_score(x,orig_string))
#return my_value corresponding to the highest score
return slave_df.ix[slave_df.score.idxmax(),'my_value']
master['my_value'] = master.original.apply(lambda x: helper(x,slave))
100万ドルの質問は、上記の適用コードを並列化できますか?
結局、master
のすべての行がslave
のすべての行と比較されます(スレーブは小さなデータセットであり、RAMにデータの多くのコピーを保持できます)。
複数の比較を実行できなかった理由がわかりません(つまり、複数の行を同時に処理できません)。
問題:どうすればいいのか、それが可能かどうかわからない。
どんな助けも大歓迎です!
これはDask.dataframeと並列化できます。
_>>> dmaster = dd.from_pandas(master, npartitions=4)
>>> dmaster['my_value'] = dmaster.original.apply(lambda x: helper(x, slave), name='my_value'))
>>> dmaster.compute()
original my_value
0 this is a Nice sentence 2
1 this is another one 3
2 stackoverflow is Nice 1
_
さらに、ここでスレッドとプロセスの使用のトレードオフについて考える必要があります。あいまいな文字列の照合ではほぼ確実にGILが解放されないため、複数のスレッドを使用してもメリットはありません。ただし、プロセスを使用すると、データがシリアル化されてマシン内を移動するため、状況が少し遅くなる可能性があります。
compute()
メソッドへの_get=
_キーワード引数を管理することにより、スレッドとプロセス、または分散システムの使用を試すことができます。
_import dask.multiprocessing
import dask.threaded
>>> dmaster.compute(get=dask.threaded.get) # this is default for dask.dataframe
>>> dmaster.compute(get=dask.multiprocessing.get) # try processes instead
_
私は似たようなものに取り組んでおり、この質問に出くわす可能性のある他の人のために、より完全な作業ソリューションを提供したいと考えていました。 @MRocklinは、残念ながら、提供されているコードスニペットに構文エラーがあります。私はDaskの専門家ではないので、パフォーマンスの考慮事項についてコメントすることはできませんが、@ MRocklinが提案したように、これでタスクを完了することができます。これはDaskバージョン0.17.2とPandasバージョン0.22.を使用しています:
import dask.dataframe as dd
import dask.multiprocessing
import dask.threaded
from fuzzywuzzy import fuzz
import pandas as pd
master= pd.DataFrame({'original':['this is a Nice sentence',
'this is another one',
'stackoverflow is Nice']})
slave= pd.DataFrame({'name':['hello world',
'congratulations',
'this is a Nice sentence ',
'this is another one',
'stackoverflow is Nice'],'my_value': [1,2,3,4,5]})
def fuzzy_score(str1, str2):
return fuzz.token_set_ratio(str1, str2)
def helper(orig_string, slave_df):
slave_df['score'] = slave_df.name.apply(lambda x: fuzzy_score(x,orig_string))
#return my_value corresponding to the highest score
return slave_df.loc[slave_df.score.idxmax(),'my_value']
dmaster = dd.from_pandas(master, npartitions=4)
dmaster['my_value'] = dmaster.original.apply(lambda x: helper(x, slave),meta=('x','f8'))
次に、結果を取得します(このインタープリターセッションと同様)。
In [6]: dmaster.compute(get=dask.multiprocessing.get)
Out[6]:
original my_value
0 this is a Nice sentence 3
1 this is another one 4
2 stackoverflow is Nice 5