dtype 对象上的累积操作

ayh*_*han 6 python dataframe pandas

我想弄清楚如何将累积函数应用于对象。对于数字,有几种替代方法,例如cumsumcumcount。还有df.expanding可以与apply. 但是我传递给的函数apply不适用于对象。

import pandas as pd
df = pd.DataFrame({"C1": [1, 2, 3, 4], 
                   "C2": [{"A"}, {"B"}, {"C"}, {"D"}], 
                   "C3": ["A", "B", "C", "D"], 
                   "C4": [["A"], ["B"], ["C"], ["D"]]})

df
Out: 
   C1   C2 C3   C4
0   1  {A}  A  [A]
1   2  {B}  B  [B]
2   3  {C}  C  [C]
3   4  {D}  D  [D]
Run Code Online (Sandbox Code Playgroud)

在数据框中,我有整数值、集合、字符串和列表。现在,如果我尝试expanding().apply(sum)我有累积总和:

df.expanding().apply(sum)
Out[69]: 
     C1   C2 C3   C4
0   1.0  {A}  A  [A]
1   3.0  {B}  B  [B]
2   6.0  {C}  C  [C]
3  10.0  {D}  D  [D]
Run Code Online (Sandbox Code Playgroud)

我的期望是,由于总和是在列表和字符串上定义的,我会得到这样的结果:

     C1   C2  C3     C4
0   1.0  {A}  A      [A]
1   3.0  {B}  AB     [A, B]
2   6.0  {C}  ABC    [A, B, C]
3  10.0  {D}  ABCD   [A, B, C, D]
Run Code Online (Sandbox Code Playgroud)

我也尝试过这样的事情:

df.expanding().apply(lambda r: reduce(lambda x, y: x+y**2, r))
Out: 
     C1   C2 C3   C4
0   1.0  {A}  A  [A]
1   5.0  {B}  B  [B]
2  14.0  {C}  C  [C]
3  30.0  {D}  D  [D]
Run Code Online (Sandbox Code Playgroud)

它按我的预期工作:先前的结果是x,当前行值为y。但是我不能减少使用x.union(y),例如。

所以,我的问题是:expanding我可以在对象上使用任何替代方法吗?该示例只是为了表明它expanding().apply()不适用于对象数据类型。我正在寻找支持将函数应用于这两个输入的通用解决方案:先前的结果和当前元素。

ayh*_*han 5

事实证明这是无法做到的。

继续相同的样本:

def burndowntheworld(ser):
    print('Are you sure?')
    return ser/0

df.select_dtypes(['object']).expanding().apply(burndowntheworld)
Out: 
    C2 C3   C4
0  {A}  A  [A]
1  {B}  B  [B]
2  {C}  C  [C]
3  {D}  D  [D]
Run Code Online (Sandbox Code Playgroud)

如果列的类型是对象,则永远不会调用该函数。大熊猫没有适用于对象的替代方案。对于rolling().apply().

从某种意义上说,这是一件好事,因为expanding.apply自定义函数的复杂度为 O(n**2)。对于 等特殊情况cumsumewma操作的递归性质可以将复杂性降低到线性时间,但在最一般的情况下,它应该计算前 n 个元素的函数,然后是前 n+1 个元素,依此类推。因此,特别是对于仅依赖于当前值和函数先前值的函数,扩展是非常低效的。更不用说在 DataFrame 中存储列表或集合从来都不是一个好主意。

所以答案是:如果您的数据不是数字并且函数依赖于先前的结果和当前元素,只需使用 for 循环。无论如何它会更有效率。