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

Предположим, у меня есть кадр данных df, который выглядит так:

Group   Id_In_Group   SomeQuantity
1        1              10
1        2              20
2        1               7
3        1              16
3        2              22
3        3               5
3        4              12
3        5              28
4        1               1
4        2              18
4        3              14
4        4               7
5        1              36

Я хотел бы выбрать только строки, имеющие по крайней мере 4 объекта в группе (таким образом, есть по крайней мере 4 строки, имеющие одинаковый номер "группы") и для которых SomeQuantity для 4-го объекта, когда сортируются в группе по возрастанию SomeQuantity, больше 20 (например).

Например, в данном Dataframe он будет возвращать только 3-ю группу, так как он имеет 4 (> = 4) члена, а его 4-й SomeQuantity (после сортировки) равен 22 (> = 20), поэтому он должен сконструировать dataframe:

Group   Id_In_Group   SomeQuantity
3        1              16
3        2              22
3        3               5
3        4              12
3        5              28

(будучи отсортированным по SomeQuantity или нет).

Может ли кто-нибудь быть добрым, чтобы помочь мне? :)

4
Matt 6 Янв 2017 в 14:58

3 ответа

Лучший ответ

Немного другой подход с использованием map, value_counts, groupby, filter:

(df[df.Group.map(df.Group.value_counts().ge(4))]
   .groupby('Group')
   .filter(lambda x: np.any(x['SomeQuantity'].sort_values().iloc[3] >= 20)))

enter image description here


Разбивка шагов:

Выполните value_counts, чтобы вычислить общее количество различных элементов, присутствующих в столбце Группа .

>>> df.Group.value_counts()

3    5
4    4
1    2
5    1
2    1
Name: Group, dtype: int64

Используйте map, который функционирует как словарь (в котором индекс становится ключом, а элементы серии становятся значениями), чтобы отобразить эти результаты обратно в исходный DF

>>> df.Group.map(df.Group.value_counts())

0     2
1     2
2     1
3     5
4     5
5     5
6     5
7     5
8     4
9     4
10    4
11    4
12    1
Name: Group, dtype: int64

Затем мы проверяем элементы, имеющие значение 4 или более, которое является нашим пороговым пределом, и выбираем только те подмножества из всего DF.

>>> df[df.Group.map(df.Group.value_counts().ge(4))]   

    Group  Id_In_Group  SomeQuantity
3       3            1            16
4       3            2            22
5       3            3             5
6       3            4            12
7       3            5            28
8       4            1             1
9       4            2            28
10      4            3            14
11      4            4             7

Чтобы использовать операцию groupby.filter для этого, мы должны убедиться, что мы возвращаем одно логическое значение, соответствующее каждому сгруппированному ключу, когда мы выполняем процесс сортировки, и сравниваем четвертый элемент с порогом, равным 20. np.any возвращает все такие возможности, соответствующие нашему фильтру.

>>> df[df.Group.map(df.Group.value_counts().ge(4))]         \
      .groupby('Group').apply(lambda x: x['SomeQuantity'].sort_values().iloc[3])

 Group
3    22
4    18
dtype: int64

Из них мы сравниваем четвертый элемент .iloc[3], поскольку он проиндексирован на основе 0, и возвращаем все такие благоприятные совпадения.

3
Nickil Maveli 14 Янв 2017 в 12:00

Вот так я проработал твой вопрос, бородавки и все. Я уверен, что есть гораздо более приятные способы сделать это.

Найти группы с "4 объектами в группе"

import collections

groups = list({k for k, v in collections.Counter(df.Group).items() if v > 3} );groups

Out:[3, 4]

Используйте эти группы для фильтрации нового df, содержащего эти группы:

df2 = df[df.Group.isin(groups)]

«Четвёртое SomeQuantity (после сортировки) равно 22 (> = 20)»

 df3 = df2.sort_values(by='SomeQuantity',ascending=False)

(Обновлено согласно комментарию ниже ...)

df3.groupby('Group').filter(lambda grp: any(grp.sort_values('SomeQuantity').iloc[3] >= 20)).sort_index()

    Group   Id_In_Group SomeQuantity
  3    3        1       16
  4    3        2       22
  5    3        3       5
  6    3        4       12
  7    3        5       28
1
ade1e 6 Янв 2017 в 18:32

Я бы использовал .groupby() + .filter() методы:

In [66]: df.groupby('Group').filter(lambda x: len(x) >= 4 and x['SomeQuantity'].max() >= 20)
Out[66]:
   Group  Id_In_Group  SomeQuantity
3      3            1            16
4      3            2            22
5      3            3             5
6      3            4            12
7      3            5            28
5
MaxU 6 Янв 2017 в 12:03