【问题标题】:Apply expanding function on dataframe在数据框上应用扩展功能
【发布时间】:2020-01-19 12:07:26
【问题描述】:

我有一个函数希望应用于 pandas DataFrame 的子集,以便在同一组的所有行(直到当前行)上计算该函数 - 即使用 groupby 然后 expanding .

例如,这个数据框:

df = pd.DataFrame.from_dict(
    {
        'group': ['A','A','A','B','B','B'],
        'time': [1,2,3,1,2,3],
        'x1': [10,40,30,100,200,300],
        'x2': [1,0,1,2,0,3]
                  }).sort_values('time')

    group   time    x1      x2
0   A       1       10      1
3   B       1       100     2
1   A       2       40      2
4   B       2       200     0
2   A       3       30      1
5   B       3       300     3

还有这个函数,例如:

def foo(_df):
    return _df['x1'].max() * _df['x2'].iloc[-1]

[根据 jezrael 的反馈为清晰起见进行了编辑:我的实际功能更复杂,并且不能轻易地分解为该任务的组件。这个简单的函数只适用于 MCVE。]

我想做类似的事情: df['foo_result'] = df.groupby('group').expanding().apply(foo, raw=False)

要获得这个结果:

    group   time    x1  x2  foo_result
0   A       1       10  1   10
3   B       1       100 2   200
1   A       2       40  2   80
4   B       2       200 0   0
2   A       3       30  1   40
5   B       3       300 3   900

问题是,运行df.groupby('group').expanding().apply(foo, raw=False) 会导致KeyError: 'x1'

是否有正确的方法来运行它,或者在pandas 中不将我的功能分解为组件就不可能这样做?

【问题讨论】:

  • _df['x2'].iloc[-1] 是什么意思? x2 的上一行值?从您的预期输出来看,它似乎不是这样(看起来您正在那里占据当前行......)
  • .iloc[-1] 是最后一行,不是上一行。

标签: python pandas dataframe


【解决方案1】:

一种可能的解决方案是使expanding成为函数的一部分,并使用GroupBy.apply

def foo1(_df):
    return _df['x1'].expanding().max() * _df['x2'].expanding().apply(lambda x: x[-1], raw=True)

df['foo_result'] = df.groupby('group').apply(foo1).reset_index(level=0, drop=True)
print (df)
  group  time   x1  x2  foo_result
0     A     1   10   1        10.0
3     B     1  100   2       200.0
1     A     2   40   2        80.0
4     B     2  200   0         0.0
2     A     3   30   1        40.0
5     B     3  300   3       900.0

这不是直接解决将数据帧函数应用于expanding 数据帧的问题,但它实现了相同的功能。

【讨论】:

  • 代替右边的乘法 - 你可以这样做:s = g['x1'].expanding().max() // df['foo_result'] = s.reset_index(level=0, drop=True)*df['x2']
  • 感谢您的帮助,但这个函数只是我为一个最小的、可重现的例子而编造的;以这种方式将我的实际功能分解为它的组件不是我需要的
  • @ItamarMushkin 嗯,我尝试回答 Problem is, functions on .expanding() don't work on entire dataframe, only per column... So, what can I do instead?
  • 我明白了……那我的问题还不够清楚。我已根据您的反馈对其进行了编辑。
【解决方案2】:

显然不可能在 expanding 窗口上应用数据框函数(至少对于 pandas 版本 0.23.0;已编辑 - 也不是 1.3.0),正如将 print 语句插入到函数。

在给定的 DataFrame 上运行 df.groupby('group').expanding().apply(lambda x: bool(print(x)) , raw=False)(其中 print 周围的 bool 只是为了获得有效的返回值)返回:

0    1.0
dtype: float64
0    1.0
1    2.0
dtype: float64
0    1.0
1    2.0
2    3.0
dtype: float64
0    10.0
dtype: float64
0    10.0
1    40.0
dtype: float64
0    10.0
1    40.0
2    30.0
dtype: float64

(等等 - 当然,每个单元格中还会返回一个带有“0.0”的数据框)。

这表明expanding 窗口在逐列的基础上工作(我们看到首先打印扩展的time 系列,然后是x1,依此类推),并不能真正工作数据框 - 因此不能将数据框函数应用于它。

因此,要获得获得的功能,必须将 expanding 放入数据框函数中,就像在接受的答案中一样。

【讨论】:

    猜你喜欢
    • 2021-07-12
    • 2020-10-21
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多