我有一个包含多列的数据帧.对于每一列,我希望返回一个指示符(1或-1),当当前行值是滚动平均值的定义倍数时,更改该列的滚动平均值是否重置.更复杂的是,我不希望在上一次重置后滚动窗口达到最小长度之前进行重置.

以下是一个倍数为2、最小长度为4、起始指示符值为1的示例

正在启动数据帧:

df = pd.DataFrame(
    {
        "A": [0.1, 0.1, 0.15, 0.1, 0.1, 0.7, 0.1, 0.1, 0.5, 1, 0.1, 0.1],
        "B": [0.1, 0.1, 0.4, 0.1, 0.8, 0.1, 0.1, 0.1, 0.1, 0.1, 0.9, 0.1],
    },
    index=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
)
print(df)

       A    B
0   0.10  0.1
1   0.10  0.1
2   0.15  0.4
3   0.10  0.1
4   0.10  0.8
5   0.70  0.1
6   0.10  0.1
7   0.10  0.1
8   0.50  0.1
9   1.00  0.1
10  0.10  0.9
11  0.10  0.1

我想获得:

    A  B
0   1  1
1   1  1
2   1  1
3   1  1
4   1 -1
5  -1 -1
6  -1 -1
7  -1 -1
8  -1 -1
9   1 -1
10  1  1
11  1  1

以A栏为例:

  • 第一次重置发生在第5行,0.7&>=2*平均值(第0行到第5行),我们观察到了6行
  • 第8行没有发生任何情况,因为新的滚动平均值只有3个观测值
  • 下一次重置发生在第9行,1&>=2*平均值(第6行到第9行),我们已经观察到4行

我看过各种帖子,最接近的是下面的帖子,但似乎没有一个帖子真正完全解决了这个问题:

推荐答案

您可以try :

def rolling_mean(col, start=1, multiple=2, min_count=4):
    curr = start
    num_obs = 0
    acc = 0

    for v in col:
        acc += v
        num_obs += 1

        if num_obs < min_count:
            yield curr
            continue

        m = acc / num_obs
        if v >= multiple * m:
            curr *= -1
            num_obs = 0
            acc = 0

        yield curr


df["new_A"] = list(rolling_mean(df["A"]))
df["new_B"] = list(rolling_mean(df["B"]))

print(df)

打印:

       A    B  new_A  new_B
0   0.10  0.1      1      1
1   0.10  0.1      1      1
2   0.15  0.4      1      1
3   0.10  0.1      1      1
4   0.10  0.8      1     -1
5   0.70  0.1     -1     -1
6   0.10  0.1     -1     -1
7   0.10  0.1     -1     -1
8   0.50  0.1     -1     -1
9   1.00  0.1      1     -1
10  0.10  0.9      1      1
11  0.10  0.1      1      1

You can speed-up the computation using :

from numba import njit


@njit
def rolling_mean_numba(col, start=1, multiple=2, min_count=4):
    curr = start
    num_obs = 0
    acc = 0

    out = np.empty_like(col, dtype=np.int8)

    for i, v in enumerate(col):
        acc += v
        num_obs += 1

        if num_obs < min_count:
            out[i] = curr
            continue

        m = acc / num_obs
        if v >= multiple * m:
            curr *= -1
            num_obs = 0
            acc = 0

        out[i] = curr

    return out

df["new_A"] = rolling_mean_numba(df["A"].values)
df["new_B"] = rolling_mean_numba(df["B"].values)

print(df)

Python相关问答推荐

理解Python的二分库:澄清bisect_left的使用

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

即使在可见的情况下也不相互作用

使用miniconda创建环境的问题

更改键盘按钮进入'

Pandas:将多级列名改为一级

我想一列Panadas的Rashrame,这是一个URL,我保存为CSV,可以直接点击

从spaCy的句子中提取日期

有没有一种ONE—LINER的方法给一个框架的每一行一个由整数和字符串组成的唯一id?

手动设置seborn/matplotlib散点图连续变量图例中显示的值

Python避免mypy在相互引用中从另一个类重定义类时失败

为什么在FastAPI中创建与数据库的连接时需要使用生成器?

polars:有效的方法来应用函数过滤列的字符串

在numpy数组中寻找楼梯状 struct

如何从比较函数生成ngroup?

numpy数组和数组标量之间的不同行为

Python:在cmd中添加参数时的语法

对列中的数字进行迭代,得到n次重复开始的第一个行号

为什么这个正则表达式没有捕获最后一次输入?

生产者/消费者-Queue.get by list