groupby и возвращает все строки первых n групп

У меня есть кадр данных pandas, как показано ниже.

>>> df.head()
       0      1       2          3   4           5                      6
0  35000  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000CE
1  35001  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000PE
2  35002  26000  OPTIDX      NIFTY  XX  1609425000      NIFTY20DEC10400CE
3  35003  26000  OPTIDX      NIFTY  XX  1609425000      NIFTY20DEC10400PE
4  35004  26009  OPTIDX  BANKNIFTY  XX  1499956200  BANKNIFTY1771321100CE

Я хочу сгруппировать их по столбцу 5 в отсортированном порядке и вернуть первые n групп, где n может быть задано как переменная.

Я сделал df.sort_values(5).groupby([5]), я получил <pandas.core.groupby.DataFrameGroupBy object at 0x2afc8d0>

Как получить все строки в первых двух группах. В приведенном выше примере df группа 1 будет равна 1499351400, группа 2 будет равна 1499351400, группа 3 будет равна 1609425000.

Ожидаемый результат: когда требуются группы = 2

       0      1       2          3   4           5                      6
0  35000  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000CE
1  35001  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000PE
4  35004  26009  OPTIDX  BANKNIFTY  XX  1499956200  BANKNIFTY1771321100CE

Обновление 1: после попытки @jezrael's

>>> k2=k1[k1.groupby(5).ngroup() < 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/python/2.7/lib/python2.7/site-packages/pandas/core/groupby.py", line 529, in __getattr__
    (type(self).__name__, attr))
AttributeError: 'DataFrameGroupBy' object has no attribute 'ngroup'

Дополнительно: Можно ли обойтись без панд (только питон), я не всегда могу найти машины с пандами на них. Спасибо


person pythonRcpp    schedule 03.07.2017    source источник


Ответы (2)


Если вы не можете использовать ngroup, просто ранжируйте элементы с помощью 'dense' и используйте это для индексации в df:

In [24]: df.loc[df[5].rank(method='dense') <= 2]
Out[24]: 
       0      1       2          3   4           5                      6
0  35000  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000CE
1  35001  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000PE
4  35004  26009  OPTIDX  BANKNIFTY  XX  1499956200  BANKNIFTY1771321100CE

Это работает, потому что rank(method='dense') дает нам отсортированный ранг для каждого увиденного числа:

In [25]: df[5].rank(method='dense')
Out[25]: 
0    1.0
1    1.0
2    3.0
3    3.0
4    2.0
Name: 5, dtype: float64

(P.S. По странному стечению обстоятельств я добавил и ngroup, и method='dense', так что этот вопрос меня очень радует. :-)

person DSM    schedule 03.07.2017
comment
Спасибо, а почему мы использовали .loc ? и не только df[df[5].rank(method='dense') <= 2] - person pythonRcpp; 04.07.2017

Используйте ngroup (работает в 0.20.2) с boolean indexing:

df = df.sort_values(5)

print (df.groupby(5).ngroup())
0    0
1    0
4    1
2    2
3    2
dtype: int64

df = df[df.groupby(5).ngroup() < 2]
print (df)
       0      1       2          3   4           5                      6
0  35000  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000CE
1  35001  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000PE
4  35004  26009  OPTIDX  BANKNIFTY  XX  1499956200  BANKNIFTY1771321100CE

Для более старой версии pandas используйте небольшой хак - информация скрыта в объекте grouper.group_info, поэтому выберите первый массив по [0]:

df = df.sort_values(5)

print (df.groupby([5]).grouper.group_info)
(array([0, 0, 2, 2, 1], dtype=int64), array([0, 1, 2]), 3)

print (df.groupby([5]).grouper.group_info[0])
[0 0 2 2 1]

df = df[df.groupby([5]).grouper.group_info[0] < 2]
print (df)
       0      1       2          3   4           5                      6
0  35000  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000CE
1  35001  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000PE
4  35004  26009  OPTIDX  BANKNIFTY  XX  1499956200  BANKNIFTY1771321100CE

Альтернативное решение с factorize:

df = df.sort_values(5)
df = df[pd.factorize(df[5])[0] < 2]
print (df)
       0      1       2          3   4           5                      6
0  35000  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000CE
1  35001  26009  OPTIDX  BANKNIFTY  XX  1499351400  BANKNIFTY1770621000PE
4  35004  26009  OPTIDX  BANKNIFTY  XX  1499956200  BANKNIFTY1771321100CE
person jezrael    schedule 03.07.2017
comment
ngroup правильное количество групп? чей индекс начинается с 0 справа - person pythonRcpp; 03.07.2017
comment
Точно, я добавляю вывод для ваших данных. - person jezrael; 03.07.2017
comment
Это новая функция в последней версии панд 0.20.2. Может есть проблема. - person jezrael; 03.07.2017
comment
у меня 0.19.2, есть ли другой способ, кроме ngroup, который мог бы работать в 0.19.2 - person pythonRcpp; 03.07.2017
comment
Дай мне немного времени. - person jezrael; 03.07.2017
comment
в df[pd.factorize(df[5])[0] < 2] что именно здесь делал [0] - person pythonRcpp; 04.07.2017
comment
Факторизация возвращает 2 массива в качестве выходных данных, очевидно, нужен только первый, поэтому выберите его с помощью [0]. Вы также можете проверить документы. - person jezrael; 04.07.2017