【问题标题】:Moving average for several not constant conditions几种非恒定条件的移动平均线
【发布时间】:2019-10-05 20:52:25
【问题描述】:

希望能找到高手帮忙)

有这样一张桌子

X2         X3   X4  Y   Y1
01.02.2019  1   1   1   
02.02.2019  2   2   0   
02.02.2019  2   3   0   
02.02.2019  2   1   1   
03.02.2019  1   2   1   
04.02.2019  2   3   0   
05.02.2019  1   1   1   
06.02.2019  2   2   0   
07.02.2019  1   3   1   
08.02.2019  2   1   1   
09.02.2019  1   2   0   
10.02.2019  2   3   1   
11.02.2019  1   1   0   
12.02.2019  2   2   1   
13.02.2019  1   3   0   
14.02.2019  2   1   1   
15.02.2019  1   2   1   
16.02.2019  2   3   0   
17.02.2019  1   1   1   
18.02.2019  2   2   0

在 Y1 列中,需要计算 Y 列过去 5 天的移动平均值,但只能通过条件 X3 和 X4 进行过滤。过滤器等于当前行的列的当前值。 例如,对于字符串 02/04/2019 2 3 0 平均值将等于 0,因为它只有字符串匹配条件 02.02.2019 2 3 0

怎么做我不明白,我知道它会是这样的

filtered_X4 = df ['X4']. where (condition_1 & condition_2 & condition_3)

但是如何自己设置条件condition_1,2,3我不明白。

看到了很多过滤器已知的例子,例如 condition_1 = df ['X2']. isin ([2, 3, 5]) 但这不是我需要的,因为我的条件值会随着字符串而变化

如何计算我知道的平均值

df ['Y1'] = filtered_X4.shift (1) .rolling (window = 999999, min_periods = 1) .mean ()

但无法配置过滤。

add1:这是我想要得到的结果:

X2          X3  X4  Y   Y1
01.02.2019  1   1   1   NAN
02.02.2019  2   2   0   NAN
02.02.2019  2   3   0   NAN
02.02.2019  2   1   1   NAN
03.02.2019  1   2   1   NAN
04.02.2019  2   3   0   0
05.02.2019  1   1   1   1
06.02.2019  2   2   0   0
07.02.2019  1   3   1   NAN
08.02.2019  2   1   1   NAN
09.02.2019  1   2   0   NAN
10.02.2019  2   3   1   NAN
11.02.2019  1   3   0   1
12.02.2019  2   2   1   NAN
13.02.2019  1   3   0   0
14.02.2019  2   1   1   NAN
15.02.2019  2   2   1   1
16.02.2019  2   3   0   NAN
17.02.2019  1   1   1   NAN
18.02.2019  2   2   0   1

例如,计算这条线的平均值(Y1):

    X2          X3  X4  Y   Y1
    04.02.2019  2   3   0   

我只需要从日期帧中获取字符串,其中 X3 = 2 和 X4 = 3 和 X2 从 30.01.2019 到 03.02.2019

【问题讨论】:

  • 欢迎来到堆栈溢出,这是一个有趣的问题,但我不太清楚你在做什么。您能否在问题中的示例数据框中包含您正在寻找的输出?这会很有帮助。
  • 补充资料

标签: python python-3.x pandas dataframe rolling-computation


【解决方案1】:

为此,请使用.apply()

将日期转换为日期时间。

df['X2'] = pd.to_datetime(df['X2'], format='%d.%m.%Y')

print(df)

           X2 X3 X4  Y
0  2019-02-01  1  1  1
1  2019-02-02  2  2  0
2  2019-02-02  2  3  0
3  2019-02-02  2  1  1
4  2019-02-03  1  2  1
5  2019-02-04  2  3  0
6  2019-02-05  1  1  1
7  2019-02-06  2  2  0
8  2019-02-07  1  3  1
9  2019-02-08  2  1  1
10 2019-02-09  1  2  0
11 2019-02-10  2  3  1
12 2019-02-11  1  3  0
13 2019-02-12  2  2  1
14 2019-02-13  1  3  0
15 2019-02-14  2  1  1
16 2019-02-15  2  2  1
17 2019-02-16  2  3  0
18 2019-02-17  1  1  1
19 2019-02-18  2  2  0

使用 apply 和 lambda,为每一行创建一个 df.loc 过滤器,将日期限制为前 5 天,并且还用于 X2 和 X3 列的相等性,然后计算“Y”的平均值。

df['Y1'] = df.apply(
    lambda x: df.loc[
        (
            (df.X2 < x.X2)
            & (df.X2 >= (x.X2 + pd.DateOffset(days=-4)))
            & (df.X3 == x.X3)
            & (df.X4 == x.X4)
        ),
        "Y",
    ].mean(),
    axis=1,
)


print(df)

           X2 X3 X4  Y   Y1
0  2019-02-01  1  1  1  NaN
1  2019-02-02  2  2  0  NaN
2  2019-02-02  2  3  0  NaN
3  2019-02-02  2  1  1  NaN
4  2019-02-03  1  2  1  NaN
5  2019-02-04  2  3  0  0.0
6  2019-02-05  1  1  1  1.0
7  2019-02-06  2  2  0  0.0
8  2019-02-07  1  3  1  NaN
9  2019-02-08  2  1  1  NaN
10 2019-02-09  1  2  0  NaN
11 2019-02-10  2  3  1  NaN
12 2019-02-11  1  3  0  1.0
13 2019-02-12  2  2  1  NaN
14 2019-02-13  1  3  0  0.0
15 2019-02-14  2  1  1  NaN
16 2019-02-15  2  2  1  1.0
17 2019-02-16  2  3  0  NaN
18 2019-02-17  1  1  1  NaN
19 2019-02-18  2  2  0  1.0

Y1 结果是 dtype 浮点数,因为 np.NaN 与整数系列不兼容。如果您需要整数,请使用以下workaround

col = 'Y1'

​

df[col] = df[col].fillna(-1)

df[col] = df[col].astype(int)

df[col] = df[col].astype(str)

df[col] = df[col].replace('-1', np.nan)

​

print(df)

           X2 X3 X4  Y   Y1
0  2019-02-01  1  1  1  NaN
1  2019-02-02  2  2  0  NaN
2  2019-02-02  2  3  0  NaN
3  2019-02-02  2  1  1  NaN
4  2019-02-03  1  2  1  NaN
5  2019-02-04  2  3  0    0
6  2019-02-05  1  1  1    1
7  2019-02-06  2  2  0    0
8  2019-02-07  1  3  1  NaN
9  2019-02-08  2  1  1  NaN
10 2019-02-09  1  2  0  NaN
11 2019-02-10  2  3  1  NaN
12 2019-02-11  1  3  0    1
13 2019-02-12  2  2  1  NaN
14 2019-02-13  1  3  0    0
15 2019-02-14  2  1  1  NaN
16 2019-02-15  2  2  1    1
17 2019-02-16  2  3  0  NaN
18 2019-02-17  1  1  1  NaN
19 2019-02-18  2  2  0    1

编辑

后续问题,如何每天使用新数据而不包括旧数据应用上述内容:

您只需要将数据过滤到您想要包含的数据范围内。

在日期时间中创建一个开始日期

startdate = pd.to_datetime('2019-02-13')

修改apply函数添加if条件:

df['Y1'] = df.apply(
    lambda x: (df.loc[
        (
            (df.X2 < x.X2)
            & (df.X2 >= (x.X2 + pd.DateOffset(days=-4)))
            & (df.X3 == x.X3)
            & (df.X4 == x.X4)
        ),
        "Y",
    ].mean()) if x[0] >= startdate else x[3]
    , axis=1
)

**这只会在你第一次运行 apply 语句后起作用,否则你会得到一个 out of index 错误。 **

所以先不带 if 条件运行,然后再带 if 条件运行。

【讨论】:

  • 非常感谢您的回答!还有1个问题。如何对第 20 行执行此操作而不对其余行重复此操作?比如今天做了19行,明天加了20行,怎么操作?
  • 谢谢!这就是我需要的。 :)
  • 还有一个问题。如果我有另一个块,具有相同的过滤条件,但有另一个用于计算平均值的变量(例如“Z”和“Z1”)。如何将它们组合成一个功能?分别计算多个移动平均线需要很长时间。
猜你喜欢
  • 1970-01-01
  • 2021-08-22
  • 2017-09-01
  • 2013-12-22
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 2011-06-29
相关资源
最近更新 更多