【问题标题】:How to merge (inner) two columns of a dataframe with pandas/python?如何将数据框的两列与 pandas/python 合并(内部)?
【发布时间】:2021-09-16 20:30:31
【问题描述】:

我有一个包含两列的数据框; A_ID 和 R_ID。

我想更新 R_ID 以仅包含也在 A_ID 中的值,其余的应该被删除(也是 NaN)。这些值应保持在相同的位置/索引。我知道这是一个内部连接,但我提出的解决方案遇到了几个问题。

例子:

import pandas as pd
data = {'A_ID': ['1E2', '1E3', '1E4', '1E5'], 'R_ID': ['1E7',[np.nan],[np.nan],"1E4",]}
df = pd.DataFrame(data)
print(df)

我试过了

df_A_ID = df[["A_ID"]]
df_R_ID = df[["R_ID"]]
new_df = pd.merge(df_A_ID, df_R_ID, how='inner', left_on='A_ID', right_on ='R_ID', right_index=True)

new_df = pd.concat([dataset_A_ID, dataset_R_ID],join="inner")

但是使用第一个选项我得到一个“你正在尝试合并对象和 int64 列”错误,即使两个列都是 d.types 对象,而第二个选项我得到一个空的 DataFrame。

我的预期输出将是与以前相同的数据框,但 R_ID 仅包含也在 A_ID 列中的值,位于相同的索引/位置:

data = {'A_ID': ['1E2', '1E3', '1E4', '1E5'], 'R_ID': [[np.nan],[np.nan],[np.nan],"1E4",]}
df = pd.DataFrame(data)
print(df)

【问题讨论】:

  • 请分享您的预期输出

标签: python pandas dataframe merge concatenation


【解决方案1】:

如果Series.isin 比较的列没有匹配,则将NaN 设置为Series.where

#solution working with scalar NaNs
data = {'A_ID': ['1E2', '1E3', '1E4', '1E5'], 'R_ID': ['1E7',np.nan,np.nan,"1E4",]}
df = pd.DataFrame(data)
print(df)
  A_ID R_ID
0  1E2  1E7
1  1E3  NaN
2  1E4  NaN
3  1E5  1E4

df['R_ID'] = df['R_ID'].where(df["R_ID"].isin(df["A_ID"]))
print(df)
  A_ID R_ID
0  1E2  NaN
1  1E3  NaN
2  1E4  NaN
3  1E5  1E4

或者:

df.loc[~df["R_ID"].isin(df["A_ID"]), 'R_ID'] = np.nan

【讨论】:

  • 抱歉,我编辑了我的示例,在这种情况下,像 1E4 这样的“匹配”值不一定具有相同的索引。它更像是“如果 VLOOKUP = TRUE 而不是保持,否则为 NaN”。谢谢!
【解决方案2】:

使用isin:

df['R_ID'] = df['R_ID'].loc[df['R_ID'].isin(df['A_ID'])]
>>> df
  A_ID R_ID
0  1E2  NaN
1  1E3  NaN
2  1E4  NaN
3  1E5  1E4

【讨论】:

  • 抱歉,我编辑了我的示例,在这种情况下,像 1E4 这样的“匹配”值不一定具有相同的索引。它更像是“如果 VLOOKUP = TRUE 而不是保持,否则为 NaN”。谢谢!
  • @DanielSchloß,我也更新了我的答案。 (为什么是'[nan]'?)
【解决方案3】:

它应该可以工作

df_A_ID = df[["A_ID"]].astype(dtype=pd.StringDtype())
df_R_ID = df[["R_ID"]].astype(dtype=pd.StringDtype()).reset_index()
temp_df = pd.merge(df_A_ID, df_R_ID, how='inner', left_on='A_ID', right_on ='R_ID').set_index('index')

df.loc[~(df_R_ID.isin(temp_df[['R_ID']])['R_ID']).fillna(False),'R_ID'] = [np.nan]

输出

  A_ID R_ID
0  1E2  NaN
1  1E3  NaN
2  1E4  1E4
3  1E5  NaN

【讨论】:

  • 是的,但我希望输出是原始 df,只是将不在 A_ID 列中的 R_ID 用作 NaN。
  • 如果我理解正确,我已经更新了我的答案。
猜你喜欢
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
  • 1970-01-01
  • 2021-12-14
  • 2016-10-08
  • 2021-09-10
相关资源
最近更新 更多