根据复杂的条件将列添加到pd.df

时间:2018-01-13 07:54:38

标签: pandas numpy boolean python-3.6

我有两个df看起来像这样:

In [500]: df1.iloc[67:100]
Out[500]: 
        Expiry       K Type     close
107 2018-01-26  123.00    C  0.406250
108 2018-01-26  124.00    C  0.062500
109 2018-01-26  125.00    C  0.015625
112 2018-01-26  121.50    C  1.640625
121 2018-02-23  123.50    C  0.406250
124 2018-02-23  127.50    C  0.015625
127 2018-02-23  124.50    C  0.140625
130 2018-02-23  125.50    C  0.046875
144 2018-05-25  120.00    C  3.156250
145 2018-05-25  121.00    C  2.203125
146 2018-05-25  122.00    C  1.328125
147 2018-02-23  123.00    C  0.640625
148 2018-02-23  124.00    C  0.234375
152 2018-02-23  121.50    C  1.750000
156 2018-02-23  126.50    C  0.015625
158 2018-02-23  122.50    C  0.953125
160 2018-03-23  123.25    P  0.484375
161 2018-03-23  123.50    P  0.625000
162 2018-03-23  123.75    P  0.796875
163 2018-03-23  127.25    P  4.125000
164 2018-03-23  127.50    P  4.375000

In [501]: df2
Out[501]: 
                              F       Symbol
Expiry                                      
2018-03-20 12:00:00  123.125000  ZN   MAR 18
2018-06-20 12:00:00  122.734375  ZN   JUN 18
2018-09-19 12:00:00  122.265625  ZN   SEP 18

我希望根据以下函数将“F”(从df2)添加到df1:

from pandas.tseries.offsets import MonthEnd
def find_F(df1_expiry):
    F = df2.loc[(df2.index > df1_expiry + MonthEnd(1)) &
             (df2.index < df1_expiry + MonthEnd(4))].F
    return F

应用诀窍:

df['F'] = df1['Expiry'].apply(find_F)

不确定这是最好的方式。

预期产出:

        Expiry       K Type     close  F
107 2018-01-26  123.00    C  0.406250  123.125000 
108 2018-01-26  124.00    C  0.062500  123.125000 
109 2018-01-26  125.00    C  0.015625  123.125000 
112 2018-01-26  121.50    C  1.640625  123.125000 
121 2018-02-23  123.50    C  0.406250  123.125000 
124 2018-02-23  127.50    C  0.015625  123.125000 
127 2018-02-23  124.50    C  0.140625  123.125000 
130 2018-02-23  125.50    C  0.046875  123.125000 
144 2018-05-25  120.00    C  3.156250  122.734375
145 2018-05-25  121.00    C  2.203125  122.734375
146 2018-05-25  122.00    C  1.328125  122.734375
147 2018-02-23  123.00    C  0.640625  122.734375
148 2018-02-23  124.00    C  0.234375  122.734375
152 2018-06-22  121.50    C  1.750000  122.265625
156 2018-06-22  126.50    C  0.015625  122.265625
158 2018-02-23  122.50    C  0.953125  122.734375
160 2018-03-23  123.25    P  0.484375  122.734375
161 2018-03-23  123.50    P  0.625000  122.734375
162 2018-03-23  123.75    P  0.796875  122.734375
163 2018-03-23  127.25    P  4.125000  122.734375
164 2018-03-23  127.50    P  4.375000  122.734375

我正在寻找最有效的方法。感谢任何建议。

1 个答案:

答案 0 :(得分:1)

如果输入2 DataFrames第一步是创建一个(例如通过交叉连接),然后过滤:

$('#fadeForSearch').not('body').css('opacity', '0.45');
$('#fadeForSearch').not('body').css('filter', 'alpha(opacity=45)');

编辑:

您可以使用:

df = pd.merge(df1.assign(A=1), df2.reset_index().assign(A=1)[['A','Expiry','F']], on='A')
mask = (df['Expiry_y'] > df['Expiry_x'] + pd.offsets.DateOffset(day=1, months=1)) & \
       (df['Expiry_y'] < df['Expiry_x'] + pd.offsets.DateOffset(day=31,months=6))

df = df[mask]
print (df.head())
    Expiry_x      K Type     close  A            Expiry_y           F
0 2018-01-26  123.0    C  0.406250  1 2018-03-20 12:00:00  123.125000
1 2018-01-26  123.0    C  0.406250  1 2018-06-20 12:00:00  122.734375
3 2018-01-26  124.0    C  0.062500  1 2018-03-20 12:00:00  123.125000
4 2018-01-26  124.0    C  0.062500  1 2018-06-20 12:00:00  122.734375
6 2018-01-26  125.0    C  0.015625  1 2018-03-20 12:00:00  123.125000

或者:

from pandas.tseries.offsets import MonthEnd
def find_F(df1):
    F = df2.loc[(df2.index > df1 + MonthEnd(1)) &
             (df2.index < df1 + MonthEnd(4)), 'F']
    return F.values[0]

df1['F'] = df1['Expiry'].apply(find_F)
print (df1)
        Expiry       K Type     close           F
107 2018-01-26  123.00    C  0.406250  123.125000
108 2018-01-26  124.00    C  0.062500  123.125000
109 2018-01-26  125.00    C  0.015625  123.125000
112 2018-01-26  121.50    C  1.640625  123.125000
121 2018-02-23  123.50    C  0.406250  123.125000
124 2018-02-23  127.50    C  0.015625  123.125000
127 2018-02-23  124.50    C  0.140625  123.125000
130 2018-02-23  125.50    C  0.046875  123.125000
144 2018-05-25  120.00    C  3.156250  122.734375
145 2018-05-25  121.00    C  2.203125  122.734375
146 2018-05-25  122.00    C  1.328125  122.734375
147 2018-02-23  123.00    C  0.640625  123.125000
148 2018-02-23  124.00    C  0.234375  123.125000
152 2018-02-23  121.50    C  1.750000  123.125000
156 2018-02-23  126.50    C  0.015625  123.125000
158 2018-02-23  122.50    C  0.953125  123.125000
160 2018-03-23  123.25    P  0.484375  122.734375
161 2018-03-23  123.50    P  0.625000  122.734375
162 2018-03-23  123.75    P  0.796875  122.734375
163 2018-03-23  127.25    P  4.125000  122.734375
164 2018-03-23  127.50    P  4.375000  122.734375

<强>计时

没有太大的区别,因此如果仅使用df = pd.merge(df1.assign(A=1), df2.reset_index().assign(A=1)[['A','Expiry','F']], on='A') mask = (df['Expiry_y'] > df['Expiry_x'] + MonthEnd(1)) & \ (df['Expiry_y'] < df['Expiry_x'] + MonthEnd(4)) df = df[mask].drop('Expiry_y', 1) print (df) Expiry_x K Type close A F 0 2018-01-26 123.00 C 0.406250 1 123.125000 3 2018-01-26 124.00 C 0.062500 1 123.125000 6 2018-01-26 125.00 C 0.015625 1 123.125000 9 2018-01-26 121.50 C 1.640625 1 123.125000 12 2018-02-23 123.50 C 0.406250 1 123.125000 15 2018-02-23 127.50 C 0.015625 1 123.125000 18 2018-02-23 124.50 C 0.140625 1 123.125000 21 2018-02-23 125.50 C 0.046875 1 123.125000 25 2018-05-25 120.00 C 3.156250 1 122.734375 28 2018-05-25 121.00 C 2.203125 1 122.734375 31 2018-05-25 122.00 C 1.328125 1 122.734375 33 2018-02-23 123.00 C 0.640625 1 123.125000 36 2018-02-23 124.00 C 0.234375 1 123.125000 39 2018-02-23 121.50 C 1.750000 1 123.125000 42 2018-02-23 126.50 C 0.015625 1 123.125000 45 2018-02-23 122.50 C 0.953125 1 123.125000 49 2018-03-23 123.25 P 0.484375 1 122.734375 52 2018-03-23 123.50 P 0.625000 1 122.734375 55 2018-03-23 123.75 P 0.796875 1 122.734375 58 2018-03-23 127.25 P 4.125000 1 122.734375 61 2018-03-23 127.50 P 4.375000 1 122.734375 行,DataFrame时序对两种解决方案都有好处。

如果数据较大,时间应该不同,但未经过测试。

400