熊猫“减少”和“积累”功能 - 不完整的实现

NBF*_*NBF 7 python python-itertools pandas functools

我想以类似于它们在带有列表的本机 python 中应用的方式在 Pandas 中使用reduce和accumulate函数。在itertools 和functools 实现中,reduce 和accumulate(在其他语言中有时称为fold 和cumulative fold)需要一个带有两个参数的函数。在 Pandas 中,没有类似的实现。该函数有两个参数:f(accumulated_value,popped_value)

所以,我有一个二进制变量列表,并想计算我们处于 1 状态时的持续时间数:

In [1]: from itertools import accumulate
        import pandas as pd
        drawdown_periods = [0,1,1,1,0,0,0,1,1,1,1,0,1,1,0]
Run Code Online (Sandbox Code Playgroud)

使用 lambda 函数将累积应用于此

lambda x,y: (x+y)*y
Run Code Online (Sandbox Code Playgroud)

In [2]: list(accumulate(drawdown_periods, lambda x,y: (x+y)*y))
Out[2]: [0, 1, 2, 3, 0, 0, 0, 1, 2, 3, 4, 0, 1, 2, 0]
Run Code Online (Sandbox Code Playgroud)

计算每个 drawdown_period 的长度。

有没有一种聪明但古怪的方法来提供带有两个参数的 lambda 函数?我可能在这里错过了一个技巧。

我知道 groupby 有一个可爱的配方(参见StackOverflow 如何计算 Pandas 中的连续相等值/如何使用 series/dataframe 模拟 itertools.groupby)。我会重复一遍,因为它太可爱了:

In [3]: df = pd.DataFrame(data=drawdown_periods, columns=['dd'])
       df['dd'].groupby((df['dd'] != df['dd'].shift()).cumsum()).cumsum()
Out[3]:
    0     0
    1     1
    2     2
    3     3
    4     0
    5     0
    6     0
    7     1
    8     2
    9     3
    10    4
    11    0
    12    1
    13    2
    14    0
    Name: dd, dtype: int64   
Run Code Online (Sandbox Code Playgroud)

不是我想要的解决方案。我需要一种将两个参数的 lambda 函数传递给 Pandas 原生的 reduce/accumulate 函数的方法,因为这也适用于许多其他函数式编程方法。

hil*_*lem 4

可以使用 来使其工作,但会降低效率numpy。在实践中,您可能会更好地编写临时矢量化解决方案。

使用np.frompyfunc

s = pd.Series([0,1,1,1,0,0,0,1,1,1,1,0,1,1,0])
f = numpy.frompyfunc(lambda x, y: (x+y) * y, 2, 1)
f.accumulate(series.astype(object))

0     0
1     1
2     2
3     3
4     0
5     0
6     0
7     1
8     2
9     3
10    4
11    0
12    1
13    2
14    0
dtype: object
Run Code Online (Sandbox Code Playgroud)