将计算的列添加到pandas的数据框中
我有一个OHLC价格数据集,我已经从CSVparsing成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)
我想添加各种计算列,从简单的例如Range(HL)开始,然后用布尔值来表示我将要定义的价格模式的出现,例如一个蜡烛模式,
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(co) 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"])
基本问题:如何将函数映射到列,特别是我想引用多个其他列或整个行或其他?
这篇文章涉及到从单一来源列中添加两个计算列,这个列是相近的,但不是完全相同。
稍微更高级:对于参照多个单条(T)确定的价格模式,如何从函数定义中引用不同的行(例如T-1,T-2等)?
提前谢谢了。
确切的代码会根据你想要做的每一列而有所不同,但很可能你会想要使用map
和apply
函数。 在某些情况下,您可以直接使用现有列进行计算,因为这些列是Pandas Series对象,它们也可以作为Numpy数组,它们可以自动为通常的math运算按元素进行工作。
>>> d ABC 0 11 13 5 1 6 7 4 2 8 3 6 3 4 8 7 4 0 1 7 >>> (dA + dB) / dC 0 4.800000 1 3.250000 2 1.833333 3 1.714286 4 0.142857 >>> dA > dC 0 True 1 True 2 True 3 False 4 False
如果您需要在一行中使用max和min等操作,则可以使用axis=1
的apply来为每行应用您喜欢的任何函数。 下面是一个计算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"][:-1]
切断A列的最后一个元素,然后在['C'][1:]
列的第一个元素上做['C'][1:]
切片,所以当你把这两个元素连接起来并比较它们,您将A中的每个元素与下一行中的C进行比较。
你可以按照下面的方式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"])
对于问题的第二部分,您也可以使用shift
,例如:
df['t-1'] = df['t'].shift(1)
t-1
将包含上面一行的值。
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.shift.html
您列出的前四项function也将在vector上工作,但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作为input,避免使用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
等等。这足以完全vector化你给出的样本计算,并且应该相对较快。 在执行这些计算时,可以通过临时处理数据下面的numpy数组来加速甚至更快。
对于第二部分,我会build议引入一个指示每行模式的列,并编写处理每个模式的函数族。 然后将模式分组,并将适当的function应用于每个组。