合并熊猫数据框:选择较小的绝对值

时间:2019-08-31 14:55:02

标签: python python-3.x pandas dataframe absolute-value

我有两个熊猫DataFrame:

数据框A:

date        ticker  return
2017-01-03  CRM     0.018040121229614625
2017-01-03  MSFT    -0.0033444816053511683
2017-01-04  CRM     0.024198086662915008
2017-01-04  MSFT    -0.0028809218950064386
2017-01-05  CRM     -0.0002746875429199269
2017-01-05  MSFT    0.0017687731146487362

数据框B:

date        ticker  return
2017-01-03  CRM     0.018040120991250852
2017-01-03  MSFT    -0.003344466975803595
2017-01-04  CRM     0.024198103213211475
2017-01-04  MSFT    -0.0028809268004892363
2017-01-05  CRM     -0.00027464144673694513
2017-01-05  MSFT    0.0017687829680113065

现在我需要第三个“合并”数据框:

  • 相同的列名
  • 对于每一行,我必须从DataframeA或DataframeB中选择具有较小绝对值的“返回”数据

有什么建议吗?

3 个答案:

答案 0 :(得分:2)

这是具有可运行代码的经过编辑的新答案

即使行数不相等,以下代码也将起作用。它将首先在两个数据帧上使用共同的行,然后为所需的列找到正确的值

import numpy as np
import pandas as pd

## creating dummy data to get runable code
## ---------------------------------------
n_rows = 20
sub_categories = np.random.choice(4, size=n_rows)
dic1 = {
    "a": list(range(n_rows)),
    "b": sub_categories,
    "c": np.random.randn(n_rows)
}

dic2 = {
    "a": range(n_rows),
    "b": sub_categories,
    "c": np.random.randn(n_rows)
}

df1 = pd.DataFrame(dic1)
df1.drop(index=list(np.random.choice(n_rows, 5, replace=False)), inplace=True)

df2 = pd.DataFrame(dic2)
df2.drop(index=list(np.random.choice(n_rows, 3, replace=False)), inplace=True)




## Main Answer
## ---------------------------------------------------------


## merge df1 and df2 then create new column c based which take min(abs(c_1, c_2))

result = df1.merge(df2, how="inner", on=["a","b"], suffixes=["_1", "_2"]).copy()
result["c"] = result["c_1"].where(np.abs(result["c_1"])<np.abs(result["c_2"]), 
                                   result["c_2"], axis=0)
display(result)

## finally reindex to remove extra columns
result = result.reindex(columns=["a","b","c"])
result


旧答案

您可以执行以下操作

series = df1["return"].where(np.abs(df1["return"])<np.abs(df2["return"]), df2["return"], axis=0)
series

如果返回的绝对值小于df2中的同一行,则将返回其值从df1中获取的系列,否则它将从df2中获取值

然后您可以替换df1或df2的列或它们的副本以获取所需的数据框

df1["return"] = series

答案 1 :(得分:1)

您可以使用concat来加入两个dataframe,然后使用tickergroupby分组并获得每个组的最小值:

df3=pd.concat([df1,df2]).groupby('ticker').min().reset_index()

答案 2 :(得分:0)

concat+groupby上尝试return并返回minkey=abs

(pd.concat((A,B),ignore_index=True)
   .groupby(['date','ticker'])['return'].min(key=abs).reset_index())

         date ticker    return
0  2017-01-03    CRM  0.018040
1  2017-01-03   MSFT -0.003344
2  2017-01-04    CRM  0.024198
3  2017-01-04   MSFT -0.002881
4  2017-01-05    CRM -0.000275
5  2017-01-05   MSFT  0.001769