Получить первую строку данных в Python Pandas на основе критериев
Скажем, что у меня есть такой кадр данных
import pandas as pd
df = pd.DataFrame([[1, 2, 1], [1, 3, 2], [4, 6, 3], [4, 3, 4], [5, 4, 5]], columns=['A', 'B', 'C'])
>> df
A B C
0 1 2 1
1 1 3 2
2 4 6 3
3 4 3 4
4 5 4 5
Исходная таблица более сложна с большим количеством столбцов и строк.
Я хочу получить первую строку, соответствующую некоторым критериям. Примеры:
- Получить первую строку, где A > 3 (возвращает строку 2)
- Получить первую строку, где A > 4 AND B > 3 (возвращает строку 4)
- Получить первую строку, где A > 3 AND (B > 3 OR C > 2) (возвращает строку 2)
Но, если нет какой-либо строки, которая соответствует конкретным критериям, то я хочу получить первый после того, как я просто отсортирую его по A (или другим случаям с помощью B, C и т.д.)
- Возьмите первую строку, где A > 6 (возвращает строку 4, заказывая ее по букве A desc и получив первый)
Я смог сделать это, выполнив итерацию на кадре данных (я знаю, что craps: P). Поэтому я предпочитаю более питонический способ его решения.
Ответы
Ответ 1
Этот учебник является очень хорошим для срезания pandas. Убедитесь, что вы это проверили. На некоторые фрагменты... Чтобы разрезать фрейм данных с условием, вы используете этот формат:
>>> df[condition]
Это вернет срез вашего фрейма данных, который вы можете индексировать, используя iloc
. Вот ваши примеры:
-
Получить первую строку, где A > 3 (возвращает строку 2)
>>> df[df.A > 3].iloc[0]
A 4
B 6
C 3
Name: 2, dtype: int64
Если то, что вы действительно хотите, это номер строки, вместо использования iloc
, это будет df[df.A > 3].index[0]
.
-
Получить первую строку, где A > 4 AND B > 3:
>>> df[(df.A > 4) & (df.B > 3)].iloc[0]
A 5
B 4
C 5
Name: 4, dtype: int64
-
Получить первую строку, где A > 3 AND (B > 3 OR C > 2) (возвращает строку 2)
>>> df[(df.A > 3) & ((df.B > 3) | (df.C > 2))].iloc[0]
A 4
B 6
C 3
Name: 2, dtype: int64
Теперь, с вашим последним случаем, мы можем написать функцию, которая обрабатывает случай по умолчанию для возврата отсортированного по убыванию кадра:
>>> def series_or_default(X, condition, default_col, ascending=False):
... sliced = X[condition]
... if sliced.shape[0] == 0:
... return X.sort_values(default_col, ascending=ascending).iloc[0]
... return sliced.iloc[0]
>>>
>>> series_or_default(df, df.A > 6, 'A')
A 5
B 4
C 5
Name: 4, dtype: int64
Как и ожидалось, он возвращает строку 4.
Ответ 2
Для существующих совпадений используйте query
:
df.query(' A > 3' ).head(1)
Out[33]:
A B C
2 4 6 3
df.query(' A > 4 and B > 3' ).head(1)
Out[34]:
A B C
4 5 4 5
df.query(' A > 3 and (B > 3 or C > 2)' ).head(1)
Out[35]:
A B C
2 4 6 3
Ответ 3
вы можете позаботиться о первых 3 предметах с нарезкой и головой:
-
df[df.A>=4].head(1)
-
df[(df.A>=4)&(df.B>=3)].head(1)
-
df[(df.A>=4)&((df.B>=3) * (df.C>=2))].head(1)
Условие в случае, если ничего не возвращается, вы можете обрабатывать с помощью try или if, если...
try:
output = df[df.A>=6].head(1)
assert len(output) == 1
except:
output = df.sort_values('A',ascending=False).head(1)