2017-07-11 11 views
2

パンダでのフィルタリング中に4つの基準のうち3つが満たされているかどうかを確認する最も効率的な方法は何ですか?複数の条件でフィルタリングする最良の方法は?

ターゲット単語:Stevenson

データフレーム:

私は4 bigrams = ["st", "te", "ev", "on"]のうちの少なくとも3を持っている単語を含めるには、このDFをフィルタリングする必要がある
+-----------+ 
| Names | 
+-----------+ 
| Smith  | 
| Stevens | 
| Parker | 
| Stevenson | 
| Dickson | 
| Greene | 
+-----------+ 

。単語StevensStevensonを含める必要があります。次に、目標単語とフィルタされた単語との間の類似性の尺度を計算します。

ここでは、[(st, te, ev), (st, ev, on), ....]の3つのすべての組み合わせを作成し、df.Names.str.contains("st") & df.Names.str.contains("ev")などでデータフレームをフィルタリングしています。次に、一意の行だけを残します。

私はこれがフィルタリングで最も時間を無駄にしているので、これは最も効果的な方法ではないと感じています(私が期待したように)あいまいなマッチングではありません。サイズ100kのdfでテストしていますが、実際のdfは1M行以上です。どのようにそれをより良くするためにどのようなアイデア?実際の例ではバイナリ検索が機能しません。

+1

あなたが探しているのはブーリアンのようです。それははるかに効率的になります。 (http://pandas-docs.github.io/pandas-docs-travis/#boolean-indexing) – brotherperes

+1

もっと効率的かどうかは分かりませんが、 'df [sum [[df ['Names'] .str.contains(pat)for bigrams)> = 3] '? – ayhan

+1

私はayhanが良い解決策を提案したと思います。私が追加したいと思うのは、apply + inの組み合わせがpandas str.contains(約1mの行を持っていた場合は2倍速い)より速いことができるということです。 –

答えて

2

です。 (いくつかの編集の後に)

bigrams = ["st", "te", "ev", "on"] 
df['count'] = df.Names.apply(lambda x: sum([1 for v in bigrams if v in x])) 
df[df['count'] >= 3].Names 
+0

は 'df = DataFrame({'Names':['stevens'、 'smith'、 'parker'、 'john'、 'greene'、 'dickson'、 'harsh'、 'steven'、 'stack ']}) ' – ksai

+0

私はプロファイリングをしていませんでした。 – Adam

+0

私はそれを試してみると、報告する。私よりもはるかに優れていると思います。 – pawelty

1

使用pandas.Series.applydatatypeの名前場合は、これは動作するはずstr

df[df['Names'].apply(lambda x : ('st' in x) & ('ev' in x))] 
関連する問題