【问题标题】:Complex Pandas Dataframe Manipulation复杂的 Pandas 数据框操作
【发布时间】:2017-07-27 06:48:06
【问题描述】:

我有一个看起来像这样的数据框:

import pandas as pd
df= pd.DataFrame({'ID1':['A','B','C','D','E'],\
                  'ID2':['B','A','D','C','E'],\
                  'Account':['94000','94500','94000','18300','94500'],\
                  'Amount':[100,-100,50,-50,100],\
                  'Match':['-','-','-','-','-']})
df

我正在努力寻找最有效的方法来识别“ID1”中的项目何时出现在“ID2”中,并且具有特定的 Account 值。例如,使用 Account=94500 的条件应该产生:

df= pd.DataFrame({'ID1':['A','B','C','D','E'],\
                  'ID2':['B','A','D','C','E'],\
                  'Account':['94000','94500','94000','18300','94500'],\            'Amount':[100,-100,50,-50,200],'Match':['True','-','-','-','-']})
df

即只应标记第一行,因为 A(在 ID2 中)与 Account 94500 匹配

【问题讨论】:

  • 在我发布的稍微修改的数据集下不起作用
  • 在您更新的示例中,94500 中的 E 和 ID2 与 ID1 中的 E 匹配,所以最后一行也应该是 True,不是吗?

标签: python pandas dataframe


【解决方案1】:

你的解释有点不清楚,但我想你想要这个:

mask = df[df.Account == '94500'].ID2
df.loc[df.ID1.isin(mask),"Match"] = True

  Account  Amount ID1 ID2 Match
0   94000     100   A   B  True
1   94500    -100   B   A     -
2   94000      50   C   D     -
3   18300     -50   D   C     -
4   94500     100   E   E  True

还比较两个正确答案只是为了好玩。

%timeit -r 10 df['Match'] = df['ID1'].apply(lambda x: any((df['ID2']==x) & (df['Account']=='94500')))
100 loops, best of 10: 4.21 ms per loop


 %timeit -r 10 df.loc[df.ID1.isin(df[df.Account == '94500'].ID2),"Match"] = True
1000 loops, best of 10: 1.48 ms per loop

更新以解决新用例

您提到您在要使用两列时遇到问题。同样,我不确定我是否理解正确,但这是我的看法。假设您有另一个变量 Prod,并且您想在 Account == 94500Prod == 6901 上都进行选择。

在这种情况下:

df= pd.DataFrame({'ID1':['A','B','C','D','E'],\
                  'ID2':['B','A','D','C','E'],\
                  'Account':['94000','94500','94000','18300','94500'],\
                  'Amount':[100,-100,50,-50,100],\
                  'Match':['-','-','-','-','-'],\
                  'Prod':[0,6901,0,0,0]
                })

mask = df[(df.Account == '94500') & (df.Prod == 6901)].ID2
df.loc[df.ID1.isin(mask),"Match"] = True

结果:

  Account  Amount ID1 ID2 Match  Prod
0   94000     100   A   B  True     0
1   94500    -100   B   A     -  6901
2   94000      50   C   D     -     0
3   18300     -50   D   C     -     0
4   94500     100   E   E     -     0

现在只有 ID1 中的 'A' 匹配条件,因为 'A' 在 ID2 的第 2 行,所以只选择了第一行。

【讨论】:

  • 我在尝试在稍微不同的场景中使用您的代码时绊倒了。如果我有另一个名为“Prod”的列,并且我现在想根据帐户 94500 和 Prod 6901 进行匹配,我无法让代码工作!将熊猫导入为 pd df= pd.DataFrame({'ID1':['A','B','C','D','E'],\'ID2':['B','A' ,'D','C','E'],\'账户':['94000','94500','94000','18300','94500'],\'Prod':['6901' ,'0','0','0','0'],\'金额':[100,-100,50,-50,100],\'匹配':['-','-',' -','-','-']}) df
  • 我在尝试在稍微不同的场景中使用您的代码时绊倒了。如果我有另一个名为“Prod”的列,并且我现在想根据帐户 94500 和 Prod 6901 进行匹配,我无法让代码工作! df= pd.DataFrame({'ID1':['A','B','C','D','E'],'ID2':['B','A','D', 'C','E'],'Account':['94000','94500','94000','18300','94500'],'Prod':['6901','0','0 ','0','0'],'金额':[100,-100,50,-50,100],'匹配':['-','-','-','-','- ']})。应该没有与 prod 为 6901 和帐户为 94500 的匹配项
  • 如果我理解正确,请更改条件以解决您的情况。
【解决方案2】:

你可以使用熊猫apply:

df['Match'] = df['ID1'].apply(lambda x: any((df['ID2']==x) & (df['Account']=='94500')))

这给出了:

  Account  Amount ID1 ID2  Match
0   94000     100   A   B   True
1   94500    -100   B   A  False
2   94000      50   C   D  False
3   18300     -50   D   C  False
4   94500     100   E   E   True

用语言来说,逻辑是: "对于 ID1 (apply) 中的每个元素,检查数据框中是否至少有 (any) 行 ID2 = ID1 和 Account = 94500"

【讨论】:

    猜你喜欢
    • 2016-11-17
    • 1970-01-01
    • 2014-01-05
    • 2020-05-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2015-09-13
    • 2018-05-01
    相关资源
    最近更新 更多