让Pandas groupby与itertools groupby类似

12 python group-by pandas

假设我有一个像这样的列表的Python dict:

{'Grp': ['2'   , '6'   , '6'   , '5'   , '5'   , '6'   , '6'   , '7'   , '7'   , '6'], 
'Nums': ['6.20', '6.30', '6.80', '6.45', '6.55', '6.35', '6.37', '6.36', '6.78', '6.33']}
Run Code Online (Sandbox Code Playgroud)

我可以使用itertools.groupby轻松地对数字和组密钥进行分组:

from itertools import groupby
for k, l in groupby(zip(di['Grp'], di['Nums']), key=lambda t: t[0]):
    print k, [t[1] for t in l]
Run Code Online (Sandbox Code Playgroud)

打印:

2 ['6.20']
6 ['6.30', '6.80']      # one field, key=6
5 ['6.45', '6.55']
6 ['6.35', '6.37']      # second
7 ['6.36', '6.78']
6 ['6.33']              # third
Run Code Online (Sandbox Code Playgroud)

请注意,6密钥分为三个单独的组或字段.

现在假设我的dict有相同的Pandas DataFrame(相同的数据,相同的列表顺序和相同的键):

  Grp  Nums
0   2  6.20
1   6  6.30
2   6  6.80
3   5  6.45
4   5  6.55
5   6  6.35
6   6  6.37
7   7  6.36
8   7  6.78
9   6  6.33
Run Code Online (Sandbox Code Playgroud)

如果我使用Pandas的groupby,我没有看到如何逐组迭代.相反,Pandas按键值分组:

for e in df.groupby('Grp'):
    print e
Run Code Online (Sandbox Code Playgroud)

打印:

('2',   Grp  Nums
0   2  6.20)
('5',   Grp  Nums
3   5  6.45
4   5  6.55)
('6',   Grp  Nums
1   6  6.30            
2   6  6.80                # df['Grp'][1:2] first field
5   6  6.35                # df['Grp'][5:6] second field
6   6  6.37                 
9   6  6.33)               # df['Grp'][9] third field
('7',   Grp  Nums
7   7  6.36
8   7  6.78)
Run Code Online (Sandbox Code Playgroud)

注意,6组密钥是捆在一起的; 不是单独的团体.

我的问题:是否有一种相同的方式来使用Pandas的groupby,以便6,例如,将以与Python相同的方式分成三组groupby

我试过这个:

>>> df.reset_index().groupby('Grp')['index'].apply(lambda x: np.array(x))
Grp
2                [0]
5             [3, 4]
6    [1, 2, 5, 6, 9]         # I *could* do a second groupby on this...
7             [7, 8]
Name: index, dtype: object
Run Code Online (Sandbox Code Playgroud)

但它仍然按整体Grp键分组,我需要做第二个nd.array组来分割每个键的子组.

Joe*_*ron 12

首先,您可以确定Grp列中的哪些元素与前一个元素不同,并获得累积总和以形成您需要的组:

In [9]:
    diff_to_previous = df.Grp != df.Grp.shift(1)
    diff_to_previous.cumsum()
Out[9]:

0    1
1    2
2    2
3    3
4    3
5    4
6    4
7    5
8    5
9    6
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做

df.groupby(diff_to_previous.cumsum()) 
Run Code Online (Sandbox Code Playgroud)

获得所需的groupby对象


daw*_*awg 5

好吧,不要厚脸皮,但为什么不groupby通过使用iterrows在 DataFrame 上使用 Python呢?这就是它的用途:

>>> df
  Grp  Nums
0   2  6.20
1   6  6.30
2   6  6.80
3   5  6.45
4   5  6.55
5   6  6.35
6   6  6.37
7   7  6.36
8   7  6.78
9   6  6.33

>>> from itertools import groupby
>>> for k, l in groupby(df.iterrows(), key=lambda row: row[1]['Grp']):
        print k, [t[1]['Nums'] for t in l]
Run Code Online (Sandbox Code Playgroud)

印刷:

2 ['6.20']
6 ['6.30', '6.80']
5 ['6.45', '6.55']
6 ['6.35', '6.37']
7 ['6.36', '6.78']
6 ['6.33']
Run Code Online (Sandbox Code Playgroud)

尝试让 Pandagroupby以您想要的方式行事,可能会要求很多堆叠的方法,以至于您将来重新阅读时将无法遵循它。

  • 要回答您的问题,它可能会更慢。 (4认同)