Pandas: фильтр DataFrameGroupBy (df.groupby) на основе групповых агрегатов - PullRequest
1 голос
/ 28 апреля 2020
df
| a  | b |
|----|---|
| 10 | 1 |
| 10 | 5 |
| 11 | 1 |

прямая группировка с использованием

grouped = df.groupby('a')

Позволяет получить только группы, где

selector = grouped.b.max() - grouped.b.min() >= 3

дает

df
| a  |       |
|----|-------|
| 10 | True  |
| 11 | False |

Мои вопросы, что такое эквивалент для df = df.loc[<filter condition>] при работе с DataFrameGroupBy элементами?

grouped.filter(..) возвращает DataFrame.

Есть ли способ сохранить группы при фильтрации по функциям .aggreate()? Спасибо!

Ответы [ 3 ]

2 голосов
/ 28 апреля 2020

Вы можете использовать np.ptp (от пика к пику)

df.groupby('a').b.agg(np.ptp) > 3

a
10     True
11    False
Name: b, dtype: bool
1 голос
/ 02 мая 2020

IIU C - для эквивалентного вопроса df.loc[] вы можете просто сделать:

df=df.set_index('a')\
    .loc[df.groupby('a').b.agg(np.ptp).gt(3)]\
    .reset_index()

В качестве альтернативы (решение внутреннего соединения):

selector=df.groupby('a').b.agg(np.ptp).gt(3)
selector=selector.loc[selector]
df=df.merge(selector, on='a', suffixes=["", "_dropme"])
df=df.loc[:, filter(lambda col: "_dropme" not in col, df.columns)]

Выходы:

    a  b
0  10  1
1  10  5

Ps +1 @ rafael c - за .ptp вещь

0 голосов
/ 01 мая 2020

К сожалению, я не нашел прямого решения .. Поэтому я обошел его так, используя 2 groupby:

# Build True/False Series for filter criteria
selector = df.groupby('a').b.agg(np.ptp) > 3

# Only select those 'a' which have True in filter criteria
selector = selector.loc[selector == True]

# Re-Create groups of 'a' with the filter criteria in place
# Only those groups for 'a' will be created, where the MAX-MIN of 'b' are > 3.
grouped = df.loc[df['a'].isin(selector.index)].groupby('a')
...