在熊猫中向数据框添加计算列

我有一个 OHLC 价格数据集,我解析了从 CSV 到熊猫数据框架和重采样到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-l)/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"])

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

这篇文章 处理从一个源列中添加两个计算列的问题,这个问题很接近,但并不完全接近。

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

160925 次浏览

你可以用 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"])

您希望执行的每个列的确切代码都会有所不同,但是您可能希望使用 mapapply函数。在某些情况下,您可以直接使用现有的列进行计算,因为这些列是熊猫系列对象,它们也作为 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的例子,它看起来像你的“下芯”:

>>> 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]切片,对列 C 的第一个元素进行 ['C'][1:]切片,因此当您将这两个元素排成一行并进行比较时,您将比较 A 中的每个元素与下一行中的 C 元素。

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

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

然后,t-1将包含上面 t 的值。

Http://pandas.pydata.org/pandas-docs/stable/generated/pandas

您列出的前四个函数也可以用于向量,但 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等。这足以完全向量化您给出的示例计算,并且应该相对较快。在执行这些计算时,可以通过临时使用数据底层的数组来提高速度。

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