【问题标题】:Most efficient way to create bulk new shifted weighted average columns in a pandas datframe在 pandas 数据框中创建批量新移位加权平均列的最有效方法
【发布时间】:2021-04-05 04:08:49
【问题描述】:

我有以下数据框,我正在尝试设置它以用于一些回归分析:

Date        Person     Feature1  Feature2 ....  Feature100
1/1/2020      Jim         12        15               82
1/7/2020      Jim         1         25               84
1/1/2021      Jim         12        15               85
1/1/2020      Jan         1         35               86
1/7/2020      Jan         5         15               84
1/1/2021      Jan         14        5               82

我已经创建了一些我想要转换的列的列表(大约 50 列):

l = ['Feature1','Feature2',......'Feature58']

对于在l 中找到的每一列名称,我想创建每个人最后 20 个条目的加权平均值(加权到最近的条目)并移动 1(因为我希望将其用作预测功能) .

Date        Person     Feature1  Feature2 ....  Feature100   Feature1_Shifted    Feature2_Shifted ... Feature58_Shifted
1/1/2020      Jim         12        15               82        N/A               N/A
1/7/2020      Jim         1         25               84        12               15
1/1/2021      Jim         12        15               85        6.5              20
1/1/2020      Jan         1         35               86        N/A              N/A
1/7/2020      Jan         5         15               84        1                35
1/1/2021      Jan         14        5               82         3                25

在这里根据这个问题松散地:Most Pythonic Way to Create Many New Columns in Pandas

这里的加权平均值:https://stackoverflow.com/a/57602282/13194245 可以选择更改权重。

我正在努力将所有内容合二为一(以及从哪里开始)。因此,任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 计算您链接到的加权平均值的答案使用 numpy 函数,该函数需要为每个值指定特定权重。 Pandas 有另一个计算指数(衰减)加权平均值的函数:pandas.pydata.org/docs/reference/api/pandas.DataFrame.ewm.html。这是你希望实现的吗?或者您会在自己的列中定义权重?
  • 这看起来可能是个不错的选择!我没有在他们自己的列中定义任何权重,所以听起来它会起作用!
  • 嗨@AlexK。你知道你是否可以用ewm 设置一个窗口期吗?好像不行?
  • 看看我提供的链接对你有没有帮助

标签: python pandas


【解决方案1】:

如果您可以接受指数衰减方法,那么实际上已经有一个帖子可以帮助您:Create a rolling custom EWMA on a pandas dataframe。第二个(不接受)答案实现了一个自定义函数,以允许在指定窗口上滚动 EWM 操作。

要让它与您的列列表一起使用,您只需将该代码的最后一行替换为:

l.append('Person')
ewm_df = df[l].groupby('Person').rolling(window).apply(ewma).reset_index(level=1, drop=True)

l 是您的列列表。如果您想在每个列名中添加“_shifted”,rename 作为最后一步应该会有所帮助:

ewm_df.rename({col: col + '_shifted' for col in l}, axis=1, inplace=True)

在您的情况下,窗口将是 20。

编辑

我还不确定如何使用已经提供的代码将结果添加到原始 df。除了 ewm_df 数据框中的“Person”之外,您还需要一个合并键,然后将两个 dfs 合并到两个键上。我的解决方法是在原始数据框中一一创建新列:

for col in l:
  df[f"{col}_shifted"] = df.groupby('Person')[col].rolling(window).apply(ewma).values

编辑 2

由于使用了自定义函数,所以最后可以单独进行移位操作:

for col in l:
   df[f"{col}_shifted"] = df.groupby('Person')[f"{col}_shifted"].shift()

编辑 3

好的,整个事情需要一个更复杂的陈述。下面的语句会将新的移位列添加到原始数据框中。我用一个简单的平均值测试了这个语句(用np.mean替换ewma),它有效。

for col in l:
   df[f"{col}_shifted"] = df.groupby('Person')[col].transform(lambda x: x.rolling(20).apply(ewma).shift())

【讨论】:

  • 谢谢!我在玩ewm 权重,发现质心 (com) 争论最好设置在2.5。所以在这个解决方案中,我需要以某种方式调整“阿尔法”论证?除此之外,看起来是个不错的选择
  • 我也可以在新创建的列名中添加_shifted吗?
  • documentation 中有一个com 的公式将alpha 映射到com,因此您应该能够从中得出alpha 的值。
  • @SOK 我添加了一种解决方法,用于在原始 df 中创建新列。如果我想到更好的方法,我会添加它。
  • 这太好了,非常感谢您的所有帮助
猜你喜欢
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 2020-04-17
  • 2012-07-01
  • 1970-01-01
  • 2016-02-12
相关资源
最近更新 更多