条件If语句应用于数据框的多列

时间:2019-06-26 05:27:35

标签: python pandas dataframe

我有一个分钟股票收益率的数据框,我想创建一个新列,该列取决于是否超过了收益率(正负),如果是,则该行等于限制(正负) ,否则等于已检查的最后一列。下面的示例说明了这一点:

import pandas as pd
dict = [
        {'ticker':'jpm','date': '2016-11-28','returns1': 0.02,'returns2': 0.03,'limit': 0.1},
{ 'ticker':'ge','date': '2016-11-28','returns1': 0.2,'returns2': -0.3,'limit': 0.1},
{'ticker':'fb', 'date': '2016-11-28','returns1': -0.2,'returns2': 0.5,'limit': 0.1},
]
df = pd.DataFrame(dict)
df['date']      = pd.to_datetime(df['date'])
df=df.set_index(['date','ticker'], drop=True)  

目标将是这样:

                   fin_return  limit  returns1  returns2
date       ticker                                       
2016-11-28 jpm           0.03    0.1      0.02      0.03
           ge            0.10    0.1      0.20     -0.30
           fb           -0.10    0.1     -0.20      0.50

因此,在第一行中,收益率从未超过限制,因此该值等于收益率2(0.03)中的值。在第2行中,收益超过了上行,因此该值应为正极限。在第3行中,收益率首先在下行方向超出,因此该值应为负极限。

我的实际数据帧有几千列,所以我不太确定如何执行此操作(可能是循环?)。我感谢任何建议。

该想法是测试止损或限价交易算法。无论何时触发下限,它都应将下一行替换为下限,上限也是如此,以该行中的先行者为准。因此,一旦触发了任何一个,就应该测试下一行。

我要添加一个示例,在此处再增加一列,以使其更加清晰(限制为+/- 0.1)

                   fin_return  limit  returns1  returns2 returns3
date       ticker                                       
2016-11-28 jpm           0.02    0.1      0.01      0.04    0.02
           ge            0.10    0.1      0.20     -0.30    0.6
           fb           -0.10    0.1     -0.02     -0.20    0.7

在第一行中,从未触发过限制,直到最终收益是来自returns3(0.02)。在第2行中,限制在返回值1的上方触发,因此fin_return等于上限(在该行中,在returns2和return 3中发生的任何事情都不相关)。在第3行中,返回2的下行超出了限制,因此fin_return变为-0.1,而return3中的任何内容都不相关。

1 个答案:

答案 0 :(得分:2)

使用:

dict = [
        {'ticker':'jpm','date': '2016-11-28','returns1': 0.02,'returns2': 0.03,'limit': 0.1,'returns3':0.02},
{ 'ticker':'ge','date': '2016-11-28','returns1': 0.2,'returns2': -0.3,'limit': 0.1,'returns3':0.6},
{'ticker':'fb', 'date': '2016-11-28','returns1': -0.02,'returns2': -0.2,'limit': 0.1,'returns3':0.7},
]
df = pd.DataFrame(dict)
df['date']      = pd.to_datetime(df['date'])
df=df.set_index(['date','ticker'], drop=True)  

#select all columns without first (here limit column)
df1 = df.iloc[:, 1:]

#comapre if all columns under +-limit
mask = df1.lt(df['limit'], axis=0) & df1.gt(-df['limit'], axis=0) 
m1 = mask.all(axis=1)
print (m1)
date        ticker
2016-11-28  jpm        True
            ge        False
            fb        False
dtype: bool

#replace first columns in limit with NaNs and back filling missing values, seelct first col
m2 = df1.mask(mask).bfill(axis=1).iloc[:, 0].gt(df['limit'])
print (m2)
date        ticker
2016-11-28  jpm       False
            ge         True
            fb        False
dtype: bool

arr = np.select([m1,m2, ~m2], [df1.iloc[:, -1], df['limit'], -df['limit']])
#set first column in DataFrame by insert
df.insert(0, 'fin_return', arr)
print (df)
                   fin_return  limit  returns1  returns2  returns3
date       ticker                                                 
2016-11-28 jpm           0.02    0.1      0.02      0.03      0.02
           ge            0.10    0.1      0.20     -0.30      0.60
           fb           -0.10    0.1     -0.02     -0.20      0.70