pandas中左连接中不匹配的左表记录

时间:2018-04-15 06:00:55

标签: python pandas dataframe

我有两个DataFrame,'Students'DataFrame和'Fee'DataFrame。 “费用”数据框中缺少部分学生的费用详情。我想回复所有缺少费用详情的学生的详细信息。三个字段'Class','Section'和'RollNo'组成了一个独特的组合。

Students = pd.DataFrame({
    'Class': [7, 7, 8],
    'Section': ['A', 'B', 'B'],
    'RollNo': [2, 3, 4],
    'Student': ['Ram', 'Rahim', 'Robert']
})

Fee = pd.DataFrame({
    'Class': [7, 7, 8],
    'Section': ['A', 'B', 'B'],
    'RollNo': [2, 2, 3],
    'Fee': [10, 20, 30]
})
Students

   Class  RollNo Section Student
0      7       2       A     Ram
1      7       3       B   Rahim
2      8       4       B  Robert
Fee

   Class  Fee  RollNo Section
0      7   10       2       A
1      7   20       2       B
2      8   30       3       B

基本上,当我根据上面提到的3个字段在'Students'和'Fee'DataFrames之间进行左连接时,我想找到左表中不匹配的记录。使用 Python中的Pandas 实现此目的的最简单方法是什么?

非常感谢!

2 个答案:

答案 0 :(得分:1)

如果NaN DataFrame中的Fee列中没有Fee,请使用merge {f}过滤boolean indexingisna

df = pd.merge(Students, Fee, how='left')
print (df)
   Class  RollNo Section Student   Fee
0      7       2       A     Ram  10.0
1      7       3       B   Rahim   NaN
2      8       4       B  Robert   NaN

df1 = df[df['Fee'].isna()].drop('Fee', axis=1)
#for oldier versions of pandas
#df1 = df[df['Fee'].isnull()].drop('Fee', axis=1)
print (df1)
   Class  RollNo Section Student
1      7       3       B   Rahim
2      8       4       B  Robert

使用NaN s的更一般解决方案也将参数indicator添加到merge并使用left_only过滤行:

Fee = pd.DataFrame({'Class':[7,7,8],
                    'Section':['A','B','B'],
                    'RollNo':[2,2,3],
                    'Fee':[np.nan,20,30]})
print (Fee)
   Class   Fee  RollNo Section
0      7   NaN       2       A
1      7  20.0       2       B
2      8  30.0       3       B

df = pd.merge(Students, Fee, how='left', indicator=True)
print (df)
   Class  RollNo Section Student  Fee     _merge
0      7       2       A     Ram  NaN       both
1      7       3       B   Rahim  NaN  left_only
2      8       4       B  Robert  NaN  left_only

df1 = df[df['_merge'].eq('left_only')].drop(['Fee','_merge'], axis=1)
print (df1)
   Class  RollNo Section Student
1      7       3       B   Rahim
2      8       4       B  Robert

答案 1 :(得分:1)

我对这个概念感到很有趣。

选项1

  1. pandas.concatkeys参数
  2. 一起使用
  3. 确保Students部分获得'stu'的第一级MultiIndex值。
  4. pandas.DataFrame.drop_duplicates与参数keep=False一起使用以删除所有重复项。
  5. 使用Students专注于{strong> loc部分。
  6. catted = pd.concat([Students, Fee], keys=['stu', 'fee'])
    dropped = catted.drop_duplicates(['Class', 'RollNo', 'Section'], keep=False)
    index = dropped.loc['stu'].index
    
    Students.loc[index]
    
       Class  RollNo Section Student
    1      7       3       B   Rahim
    2      8       4       B  Robert
    

    选项2

    在元组列表中使用集合,采取差异并与人为设计的数据帧合并。

    cols = ['Class', 'RollNo', 'Section']
    s = set(map(tuple, Students[cols].values))
    f = set(map(tuple, Fee[cols].values))
    
    Students.merge(pd.DataFrame(list(s - f), columns=cols))
    
       Class  RollNo Section Student
    0      7       3       B   Rahim
    1      8       4       B  Robert