首页 文章

将计算列添加到pandas中的数据框中

提问于
浏览
70

我有一个OHLC价格数据集,我已经从CSV解析为Pandas数据帧并重新采样到15分钟吧:

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 500047 entries, 1998-05-04 04:45:00 to 2012-08-07 00:15:00
Freq: 15T
Data columns:
Close    363152  non-null values
High     363152  non-null values
Low      363152  non-null values
Open     363152  non-null values
dtypes: float64(4)

我想添加各种计算列,从简单的列开始,例如期间范围(H-L),然后是布尔值,以指示我将定义的价格模式的出现 - 例如锤子蜡烛图案,样本定义:

def closed_in_top_half_of_range(h,l,c):
    return c > l + (h-1)/2

def lower_wick(o,l,c):
    return min(o,c)-l

def real_body(o,c):
    return abs(c-o)

def lower_wick_at_least_twice_real_body(o,l,c):
    return lower_wick(o,l,c) >= 2 * real_body(o,c)

def is_hammer(row):
    return lower_wick_at_least_twice_real_body(row["Open"],row["Low"],row["Close"]) \
    and closed_in_top_half_of_range(row["High"],row["Low"],row["Close"])

基本问题:如何将函数映射到列,特别是我想引用多个其他列或整行或其他什么?

This post处理从单个源列添加两个计算列,这些列很接近但不完全相同 .

稍高级:对于参考多个条形(T)确定的价格模式,如何从函数定义中引用不同的行(例如T-1,T-2等)?

4 回答

  • 40

    您列出的前四个函数也适用于向量,但lower_wick需要进行调整 . 像这样的东西,

    def lower_wick_vec(o, l, c):
        min_oc = numpy.where(o > c, c, o)
        return min_oc - l
    

    其中o,l和c是向量 . 你可以这样做,而只是将df作为输入,并避免使用numpy,虽然它会慢得多:

    def lower_wick_df(df):
        min_oc = df[['Open', 'Close']].min(axis=1)
        return min_oc - l
    

    其他三个将按原样处理列或向量 . 然后你可以完成

    def is_hammer(df):
        lw = lower_wick_at_least_twice_real_body(df["Open"], df["Low"], df["Close"]) 
        cl = closed_in_top_half_of_range(df["High"], df["Low"], df["Close"])
        return cl & lw
    

    位操作符可以对布尔向量执行设置逻辑, &and|or 等 . 这足以完全矢量化您给出的样本计算,并且应该相对较快 . 在执行这些计算时,暂时使用数据底层的numpy数组可能会加快速度 .

    对于第二部分,我建议引入一个列,指示每行的模式,并编写一系列处理每个模式的函数 . 然后按模式分组并将适当的函数应用于每个组 .

  • 63

    您可以按 row["Open"] 等方式使用 is_hammer ,如下所示

    def is_hammer(rOpen,rLow,rClose,rHigh):
        return lower_wick_at_least_twice_real_body(rOpen,rLow,rClose) \
           and closed_in_top_half_of_range(rHigh,rLow,rClose)
    

    然后你可以使用map:

    df["isHammer"] = map(is_hammer, df["Open"], df["Low"], df["Close"], df["High"])
    
  • 4

    对于您想要执行的每个列,确切的代码会有所不同,但是's likely you' ll想要使用 mapapply 函数 . 在某些情况下,您可以直接使用现有列进行计算,因为列是Pandas Series对象,它们也可用作Numpy数组,它可以自动按元素方式进行常规数学运算 .

    >>> d
        A   B  C
    0  11  13  5
    1   6   7  4
    2   8   3  6
    3   4   8  7
    4   0   1  7
    >>> (d.A + d.B) / d.C
    0    4.800000
    1    3.250000
    2    1.833333
    3    1.714286
    4    0.142857
    >>> d.A > d.C
    0     True
    1     True
    2     True
    3    False
    4    False
    

    如果需要在一行中使用max和min之类的操作,可以使用 applyaxis=1 将您喜欢的任何函数应用于每一行 . 这是一个计算 min(A, B)-C 的例子,它看起来像你的"lower wick":

    >>> d.apply(lambda row: min([row['A'], row['B']])-row['C'], axis=1)
    0    6
    1    2
    2   -3
    3   -3
    4   -7
    

    希望这能让您了解如何继续 .

    编辑:要将行与相邻行进行比较,最简单的方法是对要比较的列进行切片,从开始/结束开始,然后比较生成的切片 . 例如,这将告诉您列A中的元素小于C列中下一行元素的哪些行:

    d['A'][:-1] < d['C'][1:]
    

    这是另一种方式,告诉你哪些行的A小于前一行的C:

    d['A'][1:] < d['C'][:-1]
    

    在A列的最后一个元素上执行 ['A"][:-1] slice,并在C列的第一个元素上执行 ['C'][1:] slice,因此当您将这两个元素排成行并进行比较时,您将A中的每个元素与下一行中的C进行比较 .

  • 1

    对于问题的第二部分,您还可以使用 shift ,例如:

    df['t-1'] = df['t'].shift(1)
    

    t-1 然后将包含上面一行的值 .

    http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.shift.html

相关问题