2

我有一个 DataFrame,其中包含特定分钟结束时的(股票)价格。

DF 列是:

  • minute_id:0-1440,0 表示午夜,480 表示上午 8:00 (60*8)
  • 价格:分钟结束时的股票价格
  • 变化:价格从上一个变化。分钟
  • 方向:变化的方向
import numpy.random as nprnd
from pandas import DataFrame

n = 10    # Number of samples
# Starting at 8:00 AM, set some (n) random prices between 4-5
df = DataFrame({'minute_id': range(480,480+n), 'price':(5-4) * nprnd.random(n) + 4 })
df['change'] = df.price - df.price.shift(1)
df['direction'] = df.change.map(lambda x: 0 if x == 0 else x/abs(x))
df = df.dropna()
df

我想在这个 DF 中添加几列。

  1. 第一行到现在为止的平均价格,它将有价格。对于第 2 行,它将具有前 2 行的平均价格 对于第 n 行,它将具有前 n 行的平均价格
  2. 当前方向上“更改”列的总和(每次“方向”切换时将归零)
  3. 按当前方向计数,直到现在对于每一行,当前方向运行的这一行的编号是多少。
  4. 最后 4 行的平均价格

我可以通过一次遍历 DF 行来创建所有这些列。但我确信有一种更(pythonic|pandastic)的方式来做到这一点。

我也不确定如何处理丢失的数据(如果我在 minute_id 中有空白)


编辑:

在我想添加的 4 列中,1 和 4 很容易......

C4:这只是一个周期为 4 的滚动平均值

C1:滚动平均可以得到另一个参数的最小周期

将其设置为 1 并将窗口大小设置为 df 的长度将为集合中的每一行提供运行平均值。

df['rolling_avg'] = pd.rolling_mean(df.price, n, 1)

对于其他 2 列,我仍在努力寻找获得它的最佳方法。

4

1 回答 1

4

好的,经过大量“玩耍”后,我找到了适合我的东西。

它可能会以更“Pandastic”的方式完成,但这是完成它的合理方式。

我要感谢Andy HaydenJeffPhillip Cloud指出“熊猫的 10 分钟”它没有包含直接答案,但非常有帮助。此外,安迪·海登(Andy Hayden)派我去创造滚动平均,这对我很有帮助。


所以让我们一列一列

  • 添加第 1 列:到目前为止的平均价格

    # Rolling avg, windows size is the size of the entire DataFrame, with minimum of 1
    df['rolling_avg'] = pd.rolling_mean(df.price, n, 1)
    
  • 添加第 4 列:最后 4 行的平均价格

    df['RA_wnd_4'] = pd.rolling_mean(df.price, 4, 1)
    
  • 在当前“blcok”(方向)中添加第 2 列:“更改”列的 CumSum()

    # Adding Helper column that shows when direction have been changed 
    df['dir_change'] = (df.direction.shift(1) != df.direction).astype(int)
    # Identify the DF "blocks" for every direction change 
    df['block'] = df.dir_change.cumsum()
    # Split the DF based on those bolcks 
    grouped = df.groupby('block')
    # Add Function that will cumsum() for a block, and call it 
    def f1(group):
         return DataFrame({'rolling_count' : group.cumsum()}) 
    
    df['rolling_count'] = grouped.change.apply(f1)
    
  • 添加 col 3:当前“块”中的行号(方向)

    df['one'] = 1
    df['rolling_count'] = grouped.one.apply(f1)
    df = df.drop('one', axis=1)
    

完整代码:

import numpy.random as nprnd
from pandas import DataFrame
import pandas as pd

n = 10 # Number of samples
# Starting at 8:00 AM, set some (n) random prices between 4-5
df = DataFrame({'minute_id': range(480,480+n), 'price':(5-4) * nprnd.random(n) + 4 })
df['change'] = df.price - df.price.shift(1)
df['direction'] = df.change.map(lambda x: 0 if x == 0 else x/abs(x))
df = df.dropna()
#------------------------------------------
# Col 1, rolling Avg over the entire DF
df['rolling_avg'] = pd.rolling_mean(df.price, n, 1) 
#------------------------------------------
# Col 4, rolling Avg windows size of 4
df['RA_wnd_4'] = pd.rolling_mean(df.price, 4, 1)
#------------------------------------------
# Helper code for cols 2, 3 
# Adding Helper column that shows when direction have been changed
df['dir_change'] = (df.direction.shift(1) != df.direction).astype(int)
# Identify the DF "blocks" for every direction change
df['block'] = df.dir_change.cumsum()
# Split the DF based on those bolcks
grouped = df.groupby('block')
# Add Function that will cumsum() for a block, and call it
def f1(group):
     return DataFrame({'rolling_count' : group.cumsum()})
df['one'] = 1
#------------------------------------------
# Col 2, CumSum() of the 'change' column while in the current "blcok" (direction)
df['rolling_count'] = grouped.change.apply(f1)
#------------------------------------------
# Col 3, Count in the current "block" (Direction)
df['rolling_count'] = grouped.one.apply(f1)
df = df.drop('one', axis=1)

print df

输出:

 minute_id  price   change  direction   rolling_avg     RA_wnd_4    dir_change  block   rolling_count
1   481     4.771701    0.474349    1   4.771701    4.771701    1   1   1
2   482     4.300078    -0.471623   -1  4.535889    4.535889    1   2   1
3   483     4.946744    0.646666    1   4.672841    4.672841    1   3   1
4   484     4.529403    -0.417340   -1  4.636981    4.636981    1   4   1
5   485     4.434598    -0.094805   -1  4.596505    4.552706    0   4   2
6   486     4.171169    -0.263429   -1  4.525616    4.520479    0   4   3
7   487     4.416980    0.245810    1   4.510096    4.388038    1   5   1
8   488     4.727078    0.310098    1   4.537219    4.437456    0   5   2
9   489     4.049097    -0.677981   -1  4.482983    4.341081    1   6   1
于 2013-08-25T05:42:42.337 回答