当前位置: 首页 > article >正文

pandas中的关系型连接操作

把两张相关的表按照某一个或某一组键连接起来是一种常见操作。在关系型连接中,是十分重要的,往往用on参数表示。

pandas中的关系型连接函数mergejoin中提供了how参数来代表连接形式,分为左连接left、右连接right、内连接inner、外连接outer,它们的区别如下:

在这里插入图片描述

  • 左连接即以左表的键为准,如果右表中的键于左表存在,那么就添加到左表,否则则处理为缺失值,右连接类似处理。
  • 内连接只负责合并两边同时出现的键,而外连接则会在内连接的基础上包含只在左边出现以及只在右边出现的值,因此外连接又叫全连接。

如果出现重复的键,九一笛卡尔积的方式加入:

在这里插入图片描述

显然在不同的场合应该使用不同的连接形式。其中左连接和右连接是等价的,由于它们的结果中的键是被一侧的表确定的,因此常常用于有方向性地添加到目标表。内外连接两侧的表,经常是地位类似的(左右表位置的交换不引起结果的变化),想取出键的交集或者并集,具体的操作还需要根据业务的需求来判断。

左连接:

df1 = pd.DataFrame({'Name':['San Zhang','Si Li'], 'Age':[20,30]})
df2 = pd.DataFrame({'Name':['Si Li','Wu Wang'], 'Gender':['F','M']})
df = df1.merge(df2, on='Name', how='left')

如果两个表中想要连接的列不具备相同的列名,可以通过left_onright_on指定:

df1 = pd.DataFrame({'df1_name':['San Zhang','Si Li'], 'Age':[20,30]})
df2 = pd.DataFrame({'df2_name':['Si Li','Wu Wang'], 'Gender':['F','M']})
df = df1.merge(df2, left_on='df1_name', right_on='df2_name', how='left')

如果两个表中的列出现了重复的列名,那么可以通过suffixes参数指定。例如合并考试成绩的时候,第一个表记录了语文成绩,第二个是数学成绩:

df1 = pd.DataFrame({'Name':['San Zhang'],'Grade':[70]})
df2 = pd.DataFrame({'Name':['San Zhang'],'Grade':[80]})
df = df1.merge(df2, on='Name', how='left', suffixes=['_Chinese','_Math'])

在某些时候出现重复元素是麻烦的,例如两位同学来自不同的班级,但是姓名相同,这种时候就要指定on参数为多个列使得正确连接:

df1 = pd.DataFrame({'Name':['San Zhang', 'San Zhang'],
                    'Age':[20, 21],
                    'Class':['one', 'two']})
df2 = pd.DataFrame({'Name':['San Zhang', 'San Zhang'],
                    'Gender':['F', 'M'],
                    'Class':['two', 'one']})
df = df1.merge(df2, on=['Name', 'Class'], how='left')

184. 部门工资最高的员工 - 力扣(LeetCode)

查找出每个部门中薪资最高的员工。
任意顺序 返回结果表。

注:点开Pandas Schema可以看到测试的准备数据。使用这个可以在本地编程

data = [[1, 'Joe', 70000, 1], [2, 'Jim', 90000, 1], [3, 'Henry', 80000, 2], [4, 'Sam', 60000, 2], [5, 'Max', 90000, 1]]
employee = pd.DataFrame(data, columns=['id', 'name', 'salary', 'departmentId']).astype({'id':'Int64', 'name':'object', 'salary':'Int64', 'departmentId':'Int64'})
data = [[1, 'IT'], [2, 'Sales']]
department = pd.DataFrame(data, columns=['id', 'name']).astype({'id':'Int64', 'name':'object'})

解题思路:有两个表,首先要进行合并,因此先用merge进行合并。

df = employee.merge(department, left_on='departmentId', right_on='id', how='left')

查看当前DataFrame结构:

  id_x name_x  salary  departmentId  id_y name_y
0     1    Joe   70000             1     1     IT
1     2    Jim   90000             1     1     IT
2     3  Henry   80000             2     2  Sales
3     4    Sam   60000             2     2  Sales
4     5    Max   90000             1     1     IT

根据“如无必要,勿增实体”,同时也发现仅使用departmentIdEmployeesalary这个三个属性也可以完成操作,因此简化DataFrame:

df = df[['name_y', 'name_x', 'salary']].rename(
    columns={'name_y':'Department', 'name_x':'Employee'}
)

得到:

 Department Employee  salary
0         IT      Joe   70000
1         IT      Jim   90000
2      Sales    Henry   80000
3      Sales      Sam   60000
4         IT      Max   90000

由于要获得每个部门的最大薪资的人,所以要对Department进行分组,同时使用transform使得每个分组中的每一行都会被赋予该分组的最大值。

transform 的关键特性是它会将每个分组的最大值广播回原始 DataFrame 的形状。也就是说,每个分组中的每一行都会被赋予该分组的最大值。

max_salary_column = df.groupby('Department')['salary'].transform(max)

得到:

0    90000
1    90000
2    80000
3    80000
4    90000

之后进行布尔判断:

df = df[df['salary'] == max_salary_column]

即得到了该题的求解。

总的思路代码(本地):

import pandas as pd

data = [[1, 'Joe', 70000, 1], [2, 'Jim', 90000, 1], [3, 'Henry', 80000, 2], [4, 'Sam', 60000, 2], [5, 'Max', 90000, 1]]
employee = pd.DataFrame(data, columns=['id', 'name', 'salary', 'departmentId']).astype({'id':'Int64', 'name':'object', 'salary':'Int64', 'departmentId':'Int64'})
data = [[1, 'IT'], [2, 'Sales']]
department = pd.DataFrame(data, columns=['id', 'name']).astype({'id':'Int64', 'name':'object'})
# 左连接
df = employee.merge(department, left_on='departmentId', right_on='id', how='left')
print(df) # 输出结果

# 简化DataFrame,只保留需要的列并改名
df = df[['name_y', 'name_x', 'salary']].rename(
    columns={'name_y':'Department', 'name_x':'Employee'}
)
print(df) # 输出结果

# 按部门分组,找出每个部门的最高工资
max_salary_column = df.groupby('Department')['salary'].transform(max)
print(max_salary_column) # 输出结果

# 保留最高工资的行
df = df[df['salary'] == max_salary_column]

# 输出
print(df)

力扣:

import pandas as pd

def department_highest_salary(employee: pd.DataFrame, department: pd.DataFrame) -> pd.DataFrame:
    df = employee.merge(department, left_on='departmentId', right_on='id', how='left')
    df = df[['name_y', 'name_x', 'salary']].rename(
        columns={'name_y':'Department', 'name_x':'Employee'}
    )
    max_salary_column = df.groupby('Department')['salary'].transform(max)
    df = df[df['salary'] == max_salary_column]
    return df

Joyful-Pandas-课程详情 | Datawhale


http://www.kler.cn/a/531331.html

相关文章:

  • Nginx 运维开发高频面试题详解
  • 【文件上传】
  • MySQL锁详解
  • 网络原理(4)—— 网络层详解
  • 双指针算法思想——OJ例题扩展算法解析思路
  • 设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用
  • 1.5 Go切片使用
  • 浅谈量化感知训练(QAT)
  • 机器学习--学习计划
  • Intel 与 Yocto 项目的深度融合:全面解析与平台对比
  • 变形金刚多元宇宙
  • 【汽车电子软件架构】AutoSAR从放弃到入门专栏导读
  • 【探索篇】探索部署离线AI在Android的实际体验
  • ChatGPT提问技巧:行业热门应用提示词案例--办公应用
  • SpringAI 人工智能
  • Pandas基础08(分箱操作/时间序列/画图)
  • [SAP ABAP] 性能优化
  • 解决注入线程池的栈溢出问题
  • [LeetCode] 字符串完整版 — 双指针法 | KMP
  • 【Python】容器
  • 双目标定与生成深度图
  • AP单类平均准确率
  • MySQL 插入数据指南
  • 一文读懂 RAG:LLM 借助检索打开思路
  • 响应式编程与协程
  • Hot100之图论