【问题标题】:How to speed up dataframe std() calculation on each row?如何加快每行的数据帧 std() 计算?
【发布时间】:2020-07-21 07:27:04
【问题描述】:

我有一个简单的 pandas 数据框,我需要获取每一行的标准差值取决于前几行。我可以使用for 循环轻松做到这一点,但问题是计算需要很多时间。对于 1000 行,需要 4 秒。有什么办法可以加快速度吗?

结果:

       a
0      0
1      1
2      2
3      3
4      4
..   ...
995  995
996  996
997  997
998  998
999  999

10:21:18.320780 starting loop
10:21:22.861962 ending loop

       std
0      0.0
1      1.0
2      1.6
3      2.2
4      2.7
..     ...
995  574.9
996  575.5
997  576.1
998  576.6
999  577.2

代码:

import pandas as pd
import numpy as np
import math
from datetime import datetime

df = pd.DataFrame(data=np.arange(1000), columns=['a'])
print(df)

df_std = pd.DataFrame(0, index=np.arange(len(df)), columns=['std'])
print('{} starting loop'.format(datetime.now().strftime('%H:%M:%S.%f')))
for i in range(1, len(df_std)):
    su = np.sum([math.pow(df['a'].iloc[t], 2) for t in range(i + 1)])
    df_std['std'].iloc[i] = round(math.sqrt(su / i), 1)

print('{} ending loop'.format(datetime.now().strftime('%H:%M:%S.%f')))
print(df_std)

更新: 我需要做这样的事情:

for i in range(1, len(df_std)):
    df_std['std'].iloc[i] = df['a'].rolling(window=i).std()

这意味着我需要为每个具有不同滚动的 df 行获取 std() 值。对于 i=5 滚动将是前 5 个 df 行,对于 i=500 滚动将是 500 等等。

【问题讨论】:

  • 你能准确解释你想要达到的目标吗?您是否尝试根据所有前面的行计算滚动标准?在这种情况下,您可以使用 pandas rolling() 方法。
  • @pavel 这不是rolling() 所做的,它对最后 N 个值应用一些操作,而不是 all 以前的值。您所描述的是expanding(),它确实将操作应用于所有先前的值。 df.expanding(1).sum()df.cumsum() 相同(可能除了边缘情况?)。

标签: python pandas numpy dataframe


【解决方案1】:

我认为不需要循环:

df = pd.DataFrame(data=np.arange(20), columns=['a'])

df['std'] = np.round(np.sqrt(np.power(df['a'], 2).cumsum() / np.arange(len(df))), 1)
print (df)
     a   std
0    0   NaN
1    1   1.0
2    2   1.6
3    3   2.2
4    4   2.7
5    5   3.3
6    6   3.9
7    7   4.5
8    8   5.0
9    9   5.6
10  10   6.2
11  11   6.8
12  12   7.4
13  13   7.9
14  14   8.5
15  15   9.1
16  16   9.7
17  17  10.2
18  18  10.8
19  19  11.4

【讨论】:

  • 感谢您的回复。我粘贴了您的代码并得到零列。你有不同的结果吗?
  • np.std([0, 1]) = 0.5。问题和答案怎么是对的?
  • @BalajiAmbresh - 有循环,我创建了与循环解决方案相同的替代方案。
  • @BalajiAmbresh - 我想np.sum([math.pow(df['a'].iloc[t], 2) for t in range(i + 1)])
  • @jezrael 您的代码是他工作的正确表示。这是formula
【解决方案2】:

包含所有先前行数据的标准差计算:

stds = df.a.expanding().std(ddof=0)
print(stds.head())

输出

0    0.0
1    0.5
2    0.8
3    1.1
4    1.4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2017-04-12
    • 1970-01-01
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多