2016-04-04 30 views
2

私は、文章と用語の辞書をトピックにグループ化したデータフレームを持っています。ここで、各トピックの用語一致の数を数えたいと思います。Python pandas count文字列内の正規表現の一致数

import pandas as pd 

terms = {'animals':["fox","deer","eagle"], 
'people':['John', 'Rob','Steve'], 
'games':['basketball', 'football', 'hockey'] 
} 

df=pd.DataFrame({ 
'Score': [4,6,2,7,8], 
'Foo': ['The quick brown fox was playing basketball today','John and Rob visited the eagles nest, the foxes ran away','Bill smells like a wet dog','Steve threw the football at a deer. But the football missed','Sheriff John does not like hockey'] 
}) 

これまでのところ私は、トピックの列を作成し、単語は辞書を反復処理することによって存在している場合は1とそれをマークしています。

df = pd.concat([df, pd.DataFrame(columns=list(terms.keys()))]) 


for k, v in terms.items(): 
    for val in v: 
     df.loc[df.Foo.str.contains(val), k] = 1 


print (df) 

と私が取得:

>>> 
               Foo Score animals games \ 
0 The quick brown fox was playing basketball today  4  1  1 
1 John and Rob visited the eagles nest, the foxe...  6  1 NaN 
2       Bill smells like a wet dog  2  NaN NaN 
3 Steve threw the football at a deer. But the fo...  7  1  1 
4     Sheriff John does not like hockey  8  NaN  1 

    people 
0 NaN 
1  1 
2 NaN 
3  1 
4  1 

文に表示される各トピックの単語数をカウントするための最良の方法は何ですか? cythonを使用せずに辞書をループするより効率的な方法がありますか?

+0

あなたが本当に行ごとにあなたの条件をカウントする必要があるか、あなたは全体のデータフレームのためにそれらをカウントされますか?私。最終目標は何ですか? – MaxU

答えて

1

あなたが5倍高速Counterソリューションとして何であるかstacksplitを使用することができます。

df1 = df.Foo.str.split(expand=True).stack() 
            .reset_index(level=1, drop=True) 
            .reset_index(name='Foo') 

for k, v in terms.items(): 
    df1[k] = df1.Foo.str.contains('|'.join(terms[k])) 
#print df1 

print df1.groupby('index').sum().astype(int) 
     games animals people 
index       
0   1  1  0 
1   0  2  2 
2   0  0  0 
3   2  1  1 
4   1  0  1 

タイミング

In [233]: %timeit a(df) 
100 loops, best of 3: 4.9 ms per loop 

In [234]: %timeit b(df) 
10 loops, best of 3: 25.2 ms per loop 

コード:

def a(df): 
    df1 = df.Foo.str.split(expand=True).stack().reset_index(level=1, drop=True).reset_index(name='Foo') 
    for k, v in terms.items(): 
     df1[k] = df1.Foo.str.contains('|'.join(terms[k])) 
    return df1.groupby('index').sum().astype(int) 

def b(df): 
    from collections import Counter 

    df1 = pd.DataFrame(terms) 

    res = [] 
    for i,r in df.iterrows(): 
     s = df1.replace(Counter(r['Foo'].split())).replace('\w',0,regex=True).sum() 
     res.append(pd.DataFrame(s).T) 
    return pd.concat(res) 
+0

それはちょうどそれらの1つを数えます、文の中に複数の単語があるかもしれません。 –

+0

はい、元のコードもカウントされません。 – jezrael

1

私は行くだろうCounterreplace

from collections import Counter 

df1 = pd.DataFrame(terms) 

res = [] 
for i,r in df.iterrows(): 
    s = df1.replace(Counter(r['Foo'].split())).replace('\w',0,regex=True).sum() 
    res.append(pd.DataFrame(s).T) 


In [109]: pd.concat(res) 
Out[109]: 
    animals games people 
0  1  1  0 
0  0  0  2 
0  0  0  0 
0  0  2  1 
0  0  1  1 
+0

完全一致のために間違っている(例えば、イーグルイーグルスの) –

+0

私はちょうど大まかなマッチが必要だと知っています。 – ccsv

関連する問題