【问题标题】:Pandas groupby treat nonconsecutive as different variables?熊猫 groupby 将不连续视为不同的变量?
【发布时间】:2015-05-19 02:39:15
【问题描述】:

我想在 groupby 期间将非连续的 id 视为不同的变量,以便我可以返回 stamp 的第一个值,并将增量的总和作为新的数据帧。这是示例输入和输出。

import pandas as pd
import numpy as np

df = pd.DataFrame([np.array(['a','a','a','b','c','b','b','a','a','a']),
    np.arange(1, 11), np.ones(10)]).T

df.columns = ['id', 'stamp', 'increment']

df_result = pd.DataFrame([ np.array(['a','b','c','b','a']), 
        np.array([1,4,5,6,8]), np.array([3,1,1,2,3])]).T

df_result.columns = ['id', 'stamp', 'increment_sum']

In [2]: df
Out[2]:
  id stamp increment
0  a     1         1
1  a     2         1
2  a     3         1
3  b     4         1
4  c     5         1
5  b     6         1
6  b     7         1
7  a     8         1
8  a     9         1
9  a    10         1

In [3]: df_result
Out[3]:
   id    stamp         increment_sum
0  a     1             3
1  b     4             1
2  c     5             1
3  b     6             2
4  a     8             3

我可以通过

def get_result(d):
    sum = d.increment.sum()
    stamp = d.stamp.min()
    name = d.id.max()
    return name, stamp, sum

#idea from http://stackoverflow.com/questions/25147091/combine-consecutive-rows-with-the-same-column-values
df['key'] = (df['id'] != df['id'].shift(1)).astype(int).cumsum()

result = zip(*df.groupby([df.key]).apply(get_result))

df = pd.DataFrame(np.array(result).T)
df.columns = ['id', 'stamp', 'increment_sum']

但我确信一定有更优雅的解决方案

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    在优化代码方面不是很好,但解决了问题

    > df_group = df.groupby('id')
    

    对于groupby,我们不能单独使用id,所以在id 中添加另一个新列到groupby 取决于它是否连续

    > df['group_diff'] = df_group['stamp'].diff().apply(lambda v: float('nan') if v == 1 else v).ffill().fillna(0)
    > df
      id stamp increment  group_diff
    0  a     1         1           0
    1  a     2         1           0
    2  a     3         1           0
    3  b     4         1           0
    4  c     5         1           0
    5  b     6         1           2
    6  b     7         1           2
    7  a     8         1           5
    8  a     9         1           5
    9  a    10         1           5
    

    现在我们可以使用新列 group_diff 进行二次分组。按照 cmets 中的建议在最后添加 sort 函数以获得确切的函数

    > df.groupby(['id','group_diff']).agg({'increment':sum, 'stamp': 'first'}).reset_index()[['id', 'stamp','increment']].sort('stamp')
    
      id  stamp  increment
    0  a      1          3
    2  b      4          1
    4  c      5          1
    3  b      6          2
    1  a      8          3
    

    【讨论】:

    • 输出与预期输出不匹配。我认为您需要将其分类为我的“邮票”
    • 看起来这行得通,但是 FWIW,你可以用这里的技巧来简化 stackoverflow.com/questions/29142487/… 基本上是:(df['id'] != df['id'].shift()).cumsum() 基本上可以让你免于 lamda 和类型转换。
    • 谢谢大家的建议
    • 没有'stamp'列怎么办?
    • 而且它也有bug。如果输入是 df = pd.DataFrame([np.array(['a','a','b','b','a','a','b','b','a ','a']), np.arange(1, 11), np.ones(10)]).T 你不能分开非连续的 a 和 b。
    猜你喜欢
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 2022-11-09
    • 2016-01-17
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多