熊猫在不同长度的列上合并两个数据框

Posted

技术标签:

【中文标题】熊猫在不同长度的列上合并两个数据框【英文标题】:Pandas merge two dataframes on column with different length 【发布时间】:2021-04-27 09:37:08 【问题描述】:

我正在研究交易算法,但在尝试将 buy_orders 和 sell_orders 数据帧组合到单个数据帧订单时遇到了一些问题。

问题在 2021 年 1 月 21 日的buy_order 日期显示,我的算法建议购买,但由于尚未发现信号,因此还没有卖出订单,因此这些应该是 NAN合并时。 如果我要加入索引,则卖单将是与 sell_orders 数据框不同的股票的卖单。

buy_orders 数据框

    Date_buy    Name    Stock_Price_buy Order
26  2020-07-30  AAPL    96.19   buy
27  2020-09-30  AAPL    115.81  buy
28  2020-11-05  AAPL    119.03  buy
29  2020-11-30  AAPL    119.05  buy
30  2021-01-21  AAPL    136.87  buy
31  2020-10-11  ABBV    21.21   buy

sell_orders 数据框

    Date_sell   Name    Stock_Price_sell    Order
25  2020-07-20  AAPL    98.36   sell
26  2020-09-02  AAPL    131.40  sell
27  2020-10-20  AAPL    117.51  sell
28  2020-11-20  AAPL    117.34  sell
29  2021-01-04  AAPL    129.41  sell
30  2020-10-15  ABBV    24.23   sell

理想的结果是如下所示的订单数据框。

Index Buy_date  Name_x  Stock_Price_buy Order_x Sell_date   Name_y  Stock_Price_buy Order_y
26  2020-07-30  AAPL    96.19           buy     2020-09-02  AAPL    131.40          sell
27  2020-09-30  AAPL    115.81          buy     2020-10-20  AAPL    117.51          sell
28  2020-11-05  AAPL    119.03          buy     2020-11-20  AAPL    117.34          sell
29  2020-11-30  AAPL    119.05          buy     2021-01-04  AAPL    129.41          sell
30  2021-01-21  AAPL    136.87          buy     NaN         NaN     NaN             NaN

当 buy_orders.Name_x 和 sell_orders.Name_y 第一次不同时,订单数据框现在的样子如下。 ABBV sell_order 应该是 NANs

28  2020-11-05  AAPL    119.03  buy 2020-11-20  AAPL    117.34  sell
29  2020-11-30  AAPL    119.05  buy 2021-01-04  AAPL    129.41  sell
30  2021-01-21  AAPL    136.87  buy 2018-05-24  ABBV    24.23   sell

【问题讨论】:

我正在考虑在合并时使用一个条件,例如 if buy_orders.Date > sell_orders.Date 在所有列中插入 NAN。 【参考方案1】:

你有没有想过加入但随后声明后缀如下?

buy_orders.join(sell_orders,lsuffix='_buy', rsuffix='_sell')

        Date_buy Name_buy  Stock_Price_buy Order_buy   Date_sell Name_sell  \
26  2020-07-30     AAPL            96.19       buy  2020-09-02      AAPL   
27  2020-09-30     AAPL           115.81       buy  2020-10-20      AAPL   
28  2020-11-05     AAPL           119.03       buy  2020-11-20      AAPL   
29  2020-11-30     AAPL           119.05       buy  2021-01-04      AAPL   
30  2021-01-21     AAPL           136.87       buy         NaN       NaN   

    Stock_Price_sell Order_sell  
26            131.40       sell  
27            117.51       sell  
28            117.34       sell  
29            129.41       sell  
30               NaN        NaN  

【讨论】:

添加了我的输出的样子。正如所观察到的,ABBV sell_order 应该是 NANs 您的示例数据中的the ABBV sell_order 在哪里? 我认为没有必要,但它被添加了。 你的意思是buy_orders.merge(sell_orders, how='left',on='Name',left_index=True, right_index=True, suffixes=('_x', '_y')) 很抱歉,这并没有返回我原始帖子中显示的所需数据帧:(【参考方案2】:

假设您的数据是结构化的,它始终以买单开始并与卖单交替,并且每天只有一笔交易,并且每笔交易始终是一个大小的手数...您可以使用pd.concat。我制作了一个类似于您的简单数据框(将来,如果您在问题中包含用于制作示例数据框的代码,它会变得更容易):

buy_orders = pd.DataFrame.from_dict('Date_buy': [ pd.to_datetime('2020-11-01'), pd.to_datetime('2020-11-03'), 
                                           pd.to_datetime('2020-11-05'), pd.to_datetime('2020-11-08'), 
                                           pd.to_datetime('2020-11-10')], 
                                 'Order' : ['B','B','B','B','B'],
                                 'Name' : ['AAPL','AAPL','AAPL','AAPL','ABBV'],
                                 'Stock_Price_buy' : [1,2,3,4,5.0])

sell_orders = pd.DataFrame.from_dict('Date_sell': [ pd.to_datetime('2020-11-02'), pd.to_datetime('2020-11-04'), 
                                           pd.to_datetime('2020-11-06'), pd.to_datetime('2020-11-12'), 
                                           pd.to_datetime('2020-11-22')], 
                                 'Order' : ['S','S','S','S','S'],
                                 'Name' : ['AAPL','AAPL','AAPL','ABBV','ABBV'],
                                 'Stock_Price_sell' : [23,24,25,26,5.0])

您可以先将两个数据框堆叠起来,然后按日期和代码对其进行排序(在规范化列名之后):

buy_orders = buy_orders.rename(columns='Date_buy' : "Date", "Stock_Price_buy" : "Price")
sell_orders = sell_orders.rename(columns='Date_sell' : "Date", "Stock_Price_sell" : "Price")

df = pd.concat([buy_orders, sell_orders])
df = df.sort_values(['Date','Order']).reset_index(drop=True)

...然后制作数据帧的副本(更改列名以在后面的连接步骤中保持它们的区别):

df2 = df.copy()
df2.columns = [f"c_sell" for c in df.columns]

然后,您将两个数据帧彼此相邻连接,但在第二个数据帧上使用 .shift(-1) 以便它们偏移

df3 = pd.concat([df, df2.shift(-1)], axis=1)

最后,你可以清理垃圾行了:

cut = ( df3.Name != df3.Name_sell)

import numpy as np 
df3.loc[cut, 'Date_sell'] = np.nan
df3.loc[cut, 'Order_sell'] = np.nan
df3.loc[cut, 'Price_sell'] = np.nan

df3 = df3.drop(columns='Name_sell')

df3 = df3[df3.Order!="S"].reset_index(drop=True).copy()

这给了你类似的东西

        Date Order  Name  Price  Date_sell Order_sell  Price_sell
0 2020-11-01     B  AAPL    1.0 2020-11-02          S        23.0
1 2020-11-03     B  AAPL    2.0 2020-11-04          S        24.0
2 2020-11-05     B  AAPL    3.0 2020-11-06          S        25.0
3 2020-11-08     B  AAPL    4.0        NaT        NaN         NaN
4 2020-11-10     B  ABBV    5.0 2020-11-12          S        26.0

您不必制作所有中间数据帧等,但我将代码留在这里,以便如果您将内容粘贴到笔记本中,您可以查看步骤。

【讨论】:

以上是关于熊猫在不同长度的列上合并两个数据框的主要内容,如果未能解决你的问题,请参考以下文章

如何合并/连接两个不同长度的熊猫数据框?

合并 pandas 中列名不同且长度不同的两个数据框

如何在日期时间索引和两列上合并熊猫数据框

具有不同长度数组的熊猫

熊猫合并具有不同名称的列并避免重复[重复]

在python中合并具有不同长度和列的数据框列表