2015-07-24 3 views
4

Я хочу получить все строки, где (по крайней мере) один из столбцов в df [mylist] содержит True.Логическое ИЛИ на подмножестве столбцов в DataFrame

Я сейчас делаю:

df = df[ df[mylist[0]] | df[mylist[1]] | df[mylist[2]] ] 

где mylist представляет собой список строк, относящихся к столбцам df. Но я хотел бы сделать это для любой длины mylist.

Единственный способ, которым я могу это сделать, - это перебрать mylist и создать новый dataframe для каждого его элемента и слияния/concat или любого последующего. Но это не выглядит очень умным для меня.

Есть ли лучший способ?

+1

жаль ты говоришь, что 'mylist' является строка имен столбцов, таких как '['col1', 'col2', col3 ']'? Если да, то почему вы просто не делаете 'df [myList]'? – EdChum

ответ

2

Опираясь на ответ LondonRob, вы могли бы использовать

df.loc[df[mylist].any(axis=1)] 

Вызов any метода, DataFrame будет работать лучше, чем при использовании apply вызвать встроенную функцию any Питона один раз в строке.

Или вы могли бы использовать np.logical_or.reduce:

df.loc[np.logical_or.reduce(df[mylist], axis=1)] 

Для больших DataFrames, используя np.logical_or может быть быстрее:

In [30]: df = pd.DataFrame(np.random.binomial(1, 0.1, size=(100,300)).astype(bool)) 

In [31]: %timeit df.loc[np.logical_or.reduce(df, axis=1)] 
1000 loops, best of 3: 261 µs per loop 

In [32]: %timeit df.loc[df.any(axis=1)] 
1000 loops, best of 3: 636 µs per loop 

In [33]: %timeit df[df.apply(any, axis=1)] 
100 loops, best of 3: 2.13 ms per loop 

Обратите внимание, что df.any имеет дополнительные функции, такие как способность пропускать пренебрежимо малых. В этом случае, если столбцы булевозначны, то не может быть никаких NaN (поскольку значения NaN являются значениями с плавающей запятой). Так что np.logical_or.reduce быстрее.


import numpy as np 
import pandas as pd 
np.random.seed(2014) 
df = pd.DataFrame(np.random.binomial(1, 0.1, size=(10,3)).astype(bool), 
        columns=list('ABC')) 
print(df) 
#  A  B  C 
# 0 False False False 
# 1 True False False 
# 2 False False False 
# 3 True False False 
# 4 False False False 
# 5 False False False 
# 6 False True False 
# 7 False False False 
# 8 False False False 
# 9 False False False 

mylist = list('ABC') 
print(df[ df[mylist[0]] | df[mylist[1]] | df[mylist[2]] ]) 
print(df.loc[df[mylist].any(axis=1)]) 
print(df.loc[np.logical_or.reduce(df[mylist], axis=1)]) 

дает строки, в которых по крайней мере один из столбцов истинно:

 A  B  C 
1 True False False 
3 True False False 
6 False True False 
+0

Работаю, спасибо! – Andre

+0

Если бы у вас еще не было моего первосвященника, вы бы получили еще один пример времени! – LondonRob

2

Там в гораздо простой способ сделать это с помощью Python встроенный в any функции:

In []: mylist 
Out[]: ['A', 'B'] 

In []: df 
Out[]: 
     A  B  C 
0 False False False 
1 True False False 
2 False False False 
3 True False False 
4 False False False 
5 False False False 
6 False True False 
7 False False False 
8 False False False 
9 False False False 

Вы можете apply functi на any по строкам df с использованием axis=1. В этом случае я буду применять только any к подмножеству столбцов:

In []: df[mylist].apply(any, axis=1) 
Out[]: 
0 False 
1  True 
2 False 
3  True 
4 False 
5 False 
6  True 
7 False 
8 False 
9 False 
dtype: bool 

Это дает нам идеальный способ, чтобы выбрать наши ряды:

In []: df[df[mylist].apply(any, axis=1)] 
Out[]: 
     A  B  C 
1 True False False 
3 True False False 
6 False True False 
+0

Перечитав теперь более ясный вопрос, я понимаю, что мой ответ не имеет ничего общего с тем, что хотел ОП, хотя ОП сформулировал свой вопрос очень запутанным образом – EdChum

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