2014-06-27 3 views
1

Есть ли способ запроса DataFrame для строк, содержащих определенную строку в любом столбце? Что-то вроде Series.str, за исключением DataFrame? Вот то, что я до сих пор:Несколько столбцов панды векторизованной функции строки?

In [2]: s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est" 

In [3]: df = pd.DataFrame(np.array(s.split(' ')).reshape((-1, 4)), columns=['one', 'two', 'three', 'four']) 

In [4]: df 
Out[4]: 
      one   two   three  four 
0  Lorem   ipsum   dolor   sit 
1  amet, consectetur adipisicing  elit, 
2   sed    do  eiusmod  tempor 
3 incididunt    ut  labore   et 
4  dolore   magna  aliqua.   Ut 
5   enim    ad   minim  veniam, 
6   quis  nostrud exercitation  ullamco 
7  laboris   nisi   ut  aliquip 
8   ex    ea  commodo consequat. 
9   Duis   aute   irure  dolor 
10   in reprehenderit   in voluptate 
11  velit   esse  cillum  dolore 
12   eu   fugiat   nulla pariatur. 
13 Excepteur   sint  occaecat cupidatat 
14   non  proident,   sunt   in 
15  culpa   qui  officia deserunt 
16  mollit   anim   id   est 

[17 rows x 4 columns] 

In [5]: mask = df['one'].str.contains('dolor') | df['two'].str.contains('dolor') | df['three'].str.contains('dolor') | df['four'].str.contains('dolor') 

In [6]: df[mask] 
Out[6]: 
     one two three four 
0 Lorem ipsum dolor  sit 
4 dolore magna aliqua.  Ut 
9  Duis aute irure dolor 
11 velit esse cillum dolore 

[4 rows x 4 columns] 

В идеале, я хотел бы заменить последние две строки с чем-то похожее на это:

df[df.ix[:, 'one':'four'].str.contains('dolor')] 

Возможно ли это?

ответ

1

У Pandas нет методов DataFrame.str (по крайней мере, пока нет). Однако, вы можете использовать

import numpy as np 
mask = np.logical_or.reduce(
    [df[col].str.contains('dolor') 
    for col in df.loc[:, 'one':'four'].columns]) 

Это немного меньше писать, и немного быстрее, чем

mask = df['one'].str.contains('dolor') | df['two'].str.contains('dolor') | df['three'].str.contains('dolor') | df['four'].str.contains('dolor') 

In [29]: %timeit mask = np.logical_or.reduce([df[col].str.contains('dolor') for col in df.loc[:, 'one':'four'].columns]); df[mask] 
1000 loops, best of 3: 761 µs per loop 

In [30]: %timeit mask = df['one'].str.contains('dolor') | df['two'].str.contains('dolor') | df['three'].str.contains('dolor') | df['four'].str.contains('dolor'); df[mask] 
1000 loops, best of 3: 1.13 ms per loop 
0

это даст вам информацию, если Theres «Dolor» в любом из столбцов:

df.ix[:, 'one':'four'].apply(lambda x: x.str.contains('dolor'), axis=1) 

даст вам истинное/ложное значение для каждой строки любого из столбцов

, если вы объедините это с другой применить, вы получите информацию для полных столбцов

df.ix[:, 'one':'four'].apply(lambda x: x.str.contains('dolor'), axis=1).apply(lambda x: True in x.values, axis=1) 

и используя это в качестве маски колонки даст свой результат:

df[df.ix[:, 'one':'four'].apply(lambda x: x.str.contains('dolor'), axis=1).apply(lambda x: True in x.values, axis=1)] 

однако это примерно в 3-4 раза медленнее :(это unutbu решение.

2

Вы можете использовать векторизованные операции в pd.np.char.array():

a = pd.np.char.array(df.values) 
mask = a.find('dolor')!=-1 
df2 = df.iloc[np.any(mask, axis=1)] 

и содержание df2 будет:

 one two three four 
0 Lorem ipsum dolor  sit 
4 dolore magna aliqua.  Ut 
9  Duis aute irure dolor 
11 velit esse cillum dolore 
+1

это определенно самым быстрым решением: 1000 циклов, лучше всего из 3: 358 мкс на цикл – yemu

+1

отметить, что это будет давятся Нэн (это причина, панды обнажает ул ops, так что они будут работать с отсутствующими значениями) – Jeff

Смежные вопросы