2016-04-04 24 views
2

Her bir konu için terim eşleşmeleri sayısını saymak istediğim, cümlenin yer aldığı bir terim sözlüğü ve başlıklar halinde gruplandırılmış terimler sözlüğüm var.Python panda sayısı bir dizgedeki Regex eşleşmeleri sayısını sayıyor

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'] 
}) 

Şimdiye kadar ben yarattık konular için sütunlar ve bir kelime sözlüğe üzerinde yineleme tarafından varsa 1 ile işaretlenmiş.

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) 

ve ben alıyorum:

>>> 
               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 

cümlede görünen her konu için kelimelerin sayısını en iyi yolu nedir? ve cython kullanmadan sözlüğün üzerinde daha verimli bir yol var mı?

+0

gerçekten her satır için şartlarınızı saymak gerekirse veya tüm veri çerçeve için onları sayacaktır do? Yani son hedef nedir? – MaxU

cevap

1

Sen ne stack ile split kullanabilirsiniz 5 kat daha hızlı Counter çözüm olarak:

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 

Zamanlamaları:

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 

Kodu:

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

sadece bunlardan birini sayar, bir cümlede birden fazla kelime olabilir. –

+0

Evet, ancak orijinal kod da sayılmıyor. – jezrael

1
ben gitmek istiyorum

Counter ve replace:

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

Ben sadece kaba bir maç istiyorum biliyorum regex ile daha sonra kodu demir olacak teşekkürler. –

+0

Tam eşleşme nedeniyle hatalı olan – ccsv