Используя панды, как мне эффективно отобрать большой DataFrame по группам? - PullRequest
10 голосов
/ 28 сентября 2011

Я пытаюсь выполнить выборку строк в DataFrame в соответствии с группировкой.Вот пример.Скажем, я определяю следующие данные:

from pandas import *
df = DataFrame({'group1' : ["a","b","a","a","b","c","c","c","c",
                            "c","a","a","a","b","b","b","b"],
                'group2' : [1,2,3,4,1,3,5,6,5,4,1,2,3,4,3,2,1],
                'value'  : ["apple","pear","orange","apple",
                            "banana","durian","lemon","lime",
                            "raspberry","durian","peach","nectarine",
                            "banana","lemon","guava","blackberry","grape"]})

Если я сгруппирую по group1 и group2, то число строк в каждой группе будет здесь:

In [190]: df.groupby(['group1','group2'])['value'].agg({'count':len})
Out[190]: 
      count
a  1  2    
   2  1    
   3  2    
   4  1    
b  1  2    
   2  2    
   3  1    
   4  1    
c  3  1    
   4  1    
   5  2    
   6  1    

(Еслиесть еще более краткий способ вычислить это, пожалуйста, скажите.)

Теперь я хочу создать DataFrame, который имеет одну случайно выбранную строку из каждой группы.Мое предложение сделать это так:

In [215]: from random import choice
In [216]: grouped = df.groupby(['group1','group2'])
In [217]: subsampled = grouped.apply(lambda x: df.reindex(index=[choice(range(len(x)))]))
In [218]: subsampled.index = range(len(subsampled))
In [219]: subsampled
Out[219]: 
    group1  group2  value
0   b       2       pear 
1   a       1       apple
2   b       2       pear 
3   a       1       apple
4   a       1       apple
5   a       1       apple
6   a       1       apple
7   a       1       apple
8   a       1       apple
9   a       1       apple
10  a       1       apple
11  a       1       apple

, который работает.Тем не менее, мои реальные данные имеют около 2,5 миллионов строк и 12 столбцов.Если я сделаю это грязным путем, создав собственные структуры данных, я смогу завершить эту операцию за считанные секунды.Тем не менее, моя реализация выше не заканчивается в течение 30 минут (и, похоже, не ограничена памятью).В качестве примечания, когда я попытался реализовать это в R, я сначала попытался plyr, что также не завершилось за разумное время;однако решение, использующее data.table, закончилось очень быстро.

Как мне заставить это работать быстро с pandas?Я хочу любить этот пакет, поэтому, пожалуйста, помогите!

1 Ответ

8 голосов
/ 28 сентября 2011

Я тестировал с apply, кажется, что когда есть много подгрупп, это очень медленно.Атрибут groups of grouped является dict, вы можете выбрать индекс непосредственно из него:

subsampled = df.ix[(choice(x) for x in grouped.groups.itervalues())]

EDIT: Начиная с версии 0.18.1 для панд itervalues больше не работает с объектами groupby - вы можете просто использовать.values:

subsampled = df.ix[(choice(x) for x in grouped.groups.values())]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...