Фильтрация данных в ненулевых строках - PullRequest
1 голос
/ 15 апреля 2019

У меня есть DataFrame из этой формы:

In [122]: df=pd.DataFrame({"A":["1,2,3","4,5,6",np.nan,"8"],"B":[6,7,8,9]})

In [123]: df
Out[123]:
       A  B
0  1,2,3  6
1  4,5,6  7
2    NaN  8
3      8  9

Я хочу отфильтровать строки в B, где список в A содержит определенное значение, например «4».

Я пытался использовать этот синтаксис:

df["B"][["4" in a for a in df["A"].str.split(',')]]

Но я получаю TypeError: argument of type 'float' is not iterable из-за NaN в одной из строк.Поэтому я попробовал этот синтаксис -

df["B"][["4" in a for a in df["A"].str.split(',') if pd.notnull(a)]]

Но я получаю ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

Есть идеи, как мне заставить это работать?Я попробовал несколько идей, но ни одна из них не сработала, и я не знаю, почему этот синтаксис неправильный.

Ожидаемый результат - 7.

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

Используйте альтернативу панд:

s = df.loc[df["A"].str.split(',', expand=True).eq('4').any(axis=1), 'B']
print (s)
1    7
Name: B, dtype: int64

Объяснение :

Создание кадра данных по параметру expand=True в Series.str.split:

print (df["A"].str.split(',', expand=True))
     0     1     2
0    1     2     3
1    4     5     6
2  NaN   NaN   NaN
3    8  None  None

Comapre от DataFrame.eq (==):

print (df["A"].str.split(',', expand=True).eq('4'))
       0      1      2
0  False  False  False
1   True  False  False
2  False  False  False
3  False  False  False

проверить, если хотя бы один True на строки, DataFrame.any:

print (df["A"].str.split(',', expand=True).eq('4').any(axis=1))
0    False
1     True
2    False
3    False
dtype: bool

И последний фильтр по DataFrame.loc с boolean indexing.

Ваше решение следует изменить с помощью if-else и isinstance:

mask = ["4" in a if isinstance(a, list) else False for a in df["A"].str.split(',')]

s = df.loc[mask, 'B']
1 голос
/ 15 апреля 2019

Вы можете использовать Series.str.contains

df=pd.DataFrame({"A":["14,2,3","4,5,6",np.nan,"8"],"B":[6,7,8,9]})
df[df['A'].str.contains(r'\b4\b', na=False)]

Даст вам:

    A       B
1   4,5,6   7

Тогда вы можете выбрать только столбец B.

df[df['A'].str.contains(r'\b4\b', na=False)]['B']

# Output:
1    7
Name: B, dtype: int64

РЕДАКТИРОВАТЬ:

Вместо использования .contains('4') вы должны использовать .contains(r'\b4\b').Чтобы не набирать 14 или любой другой номер, который содержит 4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...