0. Problem

  1. 这个问题类似于,现在有2个表,一个是StudentScore表,一个是StudentInfo,分别记录了学生的[‘学号’,‘姓名’,‘科目’,‘成绩’]以及[‘学号’,‘姓名’],因此我需要从第2个记录了学生基本信息的表,在第1个表中进行多列匹配,而且第一个df中,具有同样[‘学号’,‘姓名’]的index可能有多个。
  2. 一个例子:我们给StudentScore表里的同学添加class信息,class信息在StudentInfo
  • 注意1: 4班的小D是国际生,但是StudentInfo没有他的信息,虽然他参与了考试,但是我们不希望在结果中包含他的成绩
  • 注意2:1班的小EStudentInfo有他的信息,但是因为他没有参加考试,所以结果中也不应该包含他的成绩
  • 所以,最后应该保留: A B C这3位同学在math和art上的成绩,以及3位同学的班级class

1. Solutions

1.1 走过的弯路

一开始绞尽脑汁,想先提取出来index,然后根据index去取值。用了isin,也用了循环一个一个比较,但是找不到一个简洁的方法。所以换了一下思路,去描述这个“多值匹配”问题,我想找的无非是两个表的“共同点”在第一个表中的“体现/映射/投影”,不是必须非得有index才能做这件事。

1.2 改用merge

merge函数天然的包括了找“共同点”以及“体现/映射/投影”。通过设置merge的参数,可以实现“多列匹配”的需求。

因此代码如下:可以直接复制过去执行一下

# 问题情景:给StudentScore表里的同学添加class信息,class信息在StudentInfo中
# 注意1: 4班的小D是国际生,但是StudentInfo没有他的信息,虽然他参与了考试,但是我们不希望在结果中包含他的成绩
# 注意2:1班的小E,StudentInfo有他的信息,但是因为他没有参加考试,所以结果中也不应该包含他的成绩
# 最后应该保留A B C这3位同学在math和art上的成绩,以及3位同学的班级
import numpy as np
import pandas as pd

StudentScore = pd.DataFrame([[1,"A","math",99],[1,"A","art",60],[2,"B","math",99],[2,"B","art",88],[3,"C","math",91],[3,"C","art",0],[4,"D","math",100],[4,"D","art",100]],columns=['StuID','StuName','subject','score'])
StudentInfo = pd.DataFrame([[1,"A","1-1"],[1,"E","1-1"],[2,"B","1-2"],[3,"C","1-2"]],columns=['StuID','StuName','class'])
print(StudentScore)
print(StudentInfo)
features = ['StuID','StuName']
ans = pd.merge(StudentScore,StudentInfo,how="inner",on=features)
print("---after merge---")
print(ans)
print("可以看到,没有E同学和D同学的任何信息")

注意how,这里使用的是inner,它和参数on一起,体现了多列匹配并且取交集的思想

合并方式,一共四种: left,right,inner,outer,默认为 inner
left 仅使用来自左边frame的键进行匹配;
right 仅使用来自右边frame 的键进行匹配;
outer 取来自左右frame 键的并集;匹配不到的话元素设为Null
inner 取来自左右frame 键的交集,匹配不到的话元素丢失;

上述代码执行结果:

---after merge---
   StuID StuName subject  score class
0      1       A    math     99   1-1
1      1       A     art     60   1-1
2      2       B    math     99   1-2
3      2       B     art     88   1-2
4      3       C    math     91   1-2
5      3       C     art      0   1-2