Получить первую строку данных в 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 и т.д.)

  1. Возьмите первую строку, где 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].

  1. Получить первую строку, где A > 4 AND B > 3:

    >>> df[(df.A > 4) & (df.B > 3)].iloc[0]
    A    5
    B    4
    C    5
    Name: 4, dtype: int64
    
  2. Получить первую строку, где 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)