如何用PySpark DataFrame df2的值替换df1对应ID的字段值
问题描述
我有两个PySpark DataFrame:df2和df1,需要以ID作为主键,用df2中的对应值替换df1里匹配ID的字段值,同时保留df1中无匹配ID的行数据。
df2数据如下:
| ID | Total_Count | Final_A | Final_B | Final_C | Final_D |
|---|---|---|---|---|---|
| 11 | 80 | 36 | 30 | 8 | 6 |
| 4 | 80 | 36 | 30 | 8 | 6 |
| 13 | 65 | 30 | 24 | 6 | 5 |
| 12 | 56 | 26 | 21 | 5 | 4 |
| 2 | 65 | 30 | 24 | 6 | 5 |
| 1 | 56 | 26 | 21 | 5 | 4 |
df1数据如下:
| ID | Total_Count | A | B | C | D |
|---|---|---|---|---|---|
| 4 | 80 | 0 | 0 | 3 | 0 |
| 11 | 80 | 0 | 0 | 0 | 0 |
| 13 | 65 | 0 | 0 | 0 | 0 |
| 12 | 56 | 0 | 4 | 0 | 0 |
| 2 | 65 | 0 | 0 | 0 | 0 |
| 1 | 56 | 0 | 0 | 0 | 0 |
| 10 | 34 | 10 | 10 | 10 | 4 |
预期结果:
| ID | Total_Count | A | B | C | D |
|---|---|---|---|---|---|
| 11 | 80 | 36 | 30 | 8 | 6 |
| 4 | 80 | 36 | 30 | 8 | 6 |
| 13 | 65 | 30 | 24 | 6 | 5 |
| 12 | 56 | 26 | 21 | 5 | 4 |
| 2 | 65 | 30 | 24 | 6 | 5 |
| 1 | 56 | 26 | 21 | 5 | 4 |
| 10 | 34 | 10 | 10 | 10 | 4 |
解决方案
可通过左连接两个DataFrame,结合coalesce函数实现需求,代码如下:
from pyspark.sql import functions as F # 左连接df1和df2,以ID作为关联键 joined_df = df1.join(df2, on="ID", how="left") # 构造结果DataFrame:优先取df2的字段值,无匹配则保留df1原数据 result_df = joined_df.select( "ID", F.coalesce(df2.Total_Count, df1.Total_Count).alias("Total_Count"), F.coalesce(df2.Final_A, df1.A).alias("A"), F.coalesce(df2.Final_B, df1.B).alias("B"), F.coalesce(df2.Final_C, df1.C).alias("C"), F.coalesce(df2.Final_D, df1.D).alias("D") ) # 输出结果 result_df.show()
关键逻辑说明
- 左连接:
how="left"确保df1的所有行都被保留,包括ID在df2中不存在的记录(如ID=10)。 - coalesce函数:返回参数中第一个非空值,这里实现了“有匹配则用df2的值,无匹配则保留df1原值”的逻辑。
- 字段别名:将合并后的字段重命名为
df1原有字段名,保证结果结构符合预期。
内容的提问来源于stack exchange,提问作者Scope
相关产品推荐
相关产品推荐

