复杂的Pandas Dataframe操作

时间:2017-07-26 17:24:05

标签: python pandas dataframe

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

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 = 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匹配

2 个答案:

答案 0 :(得分:2)

您可以使用pandas 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”

答案 1 :(得分:2)

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

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中,所以只选择了第一行。