我试图弄清楚如何将累积函数应用于对象。对于数字,有多种选择,例如cumsum和cumcount。还有df.expanding可以与一起使用apply。但是我传递给我的功能apply不适用于对象。
cumsum
cumcount
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]
在数据框中,我具有整数值,集合,字符串和列表。现在,如果我尝试一下,expanding().apply(sum)我有累加的总和:
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]
我的期望是,由于求和是在列表和字符串上定义的,所以我会得到如下信息:
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]
我也尝试过这样的事情:
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]
它按我的预期工作:以前的结果是x,当前行的值是y。但是x.union(y)例如,我不能减少使用。
x
y
x.union(y)
因此,我的问题是:expanding我可以在对象上使用其他替代方法吗?该示例只是为了表明它expanding().apply()不适用于对象dtypes。我正在寻找一种通用解决方案,该解决方案支持将函数应用于这两个输入:先前的结果和当前的元素。
expanding
expanding().apply()
事实证明这是无法完成的。
继续相同的示例:
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]
如果列的类型是对象,则永远不会调用该函数。熊猫没有其他适用于对象的替代品。相同rolling().apply()。
rolling().apply()
从某种意义上说,这是一件好事,因为expanding.apply使用自定义函数具有O(n ** 2)复杂度。对于诸如等的特殊情况cumsum,ewma操作的递归性质可以将线性时间的复杂度降低,但是在最一般的情况下,它应该为前n个元素,然后为前n + 1个元素计算函数,依此类推。因此,特别是对于仅依赖于当前值和函数先前值的函数,扩展效率很低。更不用说将列表或集合存储在DataFrame中从来不是一个好主意。
expanding.apply
ewma
因此答案是:如果您的数据不是数字,并且函数取决于先前的结果和当前元素,则只需使用for循环即可。无论如何,它将更有效率。