Pandas PySpark:Concat两个具有列和的数据帧

Pandas PySpark:Concat两个具有列和的数据帧,pandas,pyspark,Pandas,Pyspark,我有两个PySpark数据帧,我想留下来加入 Prev_table: | user_id | earnings | start_date | end_date | |---------|--------|------------|------------| | 1 | 10 | 2020-06-01 | 2020-06-10 | | 2 | 20 | 2020-06-01 | 2020-06-10 | | 3 | 30 | 2020

我有两个PySpark数据帧,我想留下来加入

Prev_table:
| user_id | earnings | start_date | end_date   |
|---------|--------|------------|------------|
| 1       | 10     | 2020-06-01 | 2020-06-10 |
| 2       | 20     | 2020-06-01 | 2020-06-10 |
| 3       | 30     | 2020-06-01 | 2020-06-10 |

New_table:
| user_id | profit |
|---------|--------|
| 1       | 100    |
| 2       | 200    |
| 5       | 500    |
结果表是按用户id分组的两个数据帧的集合。收益列是
Prev\u table.earnings+New\u table.profit

| user_id | earnings | start_date | end_date   |
|---------|--------|------------|------------|
| 1       | 110    | 2020-06-01 | 2020-06-10 |
| 2       | 220    | 2020-06-01 | 2020-06-10 |
| 3       | 30     | 2020-06-01 | 2020-06-10 |
| 5       | 500    |            |            |
这就是Pandas concat将要做的,但在PySpark的情况下,我相信我需要使用PySparks联盟? 我也不知道如何计算这两列的和。 我知道我需要使用类似于
combined_df.agg({“收入”:“sum”}).collect()
的东西,但在使用时遇到了问题

如果您对PySpark的工作流程有任何指导,我们将不胜感激。
谢谢。

可能有更好的方法,但有一种方法是,将
利润
重命名为
收益
,然后在df2中填充缺少的列,然后用
联合
和groupby添加
agg

假设
Prev_表
df1
New_表
df2

import pyspark.sql.functions as F

df3 = df2.select("user_id",F.col("profit").alias("earnings"))

(df1.union(df3.select("*",*[F.lit(None).alias(i) 
            for i in df1.columns if i not in df3.columns]))
.groupBy("user_id").agg(F.sum("earnings").alias("earnings")
 ,F.first("start_date",ignorenulls=True).alias("start_date")
 ,F.first("end_date",ignorenulls=True).alias("end_date")).orderBy("user_id")).show()


尝试使用联接操作,然后使用union all

import pyspark.sql.functions as f

import pyspark.sql.functions as f

df = df1.join(df2, df1.user_id==df2.user_id, how='left').select(df1.user_id, (df1.earnings.cast('int')+f.when(df2.profit.cast('int').isNull(),0).otherwise(df2.profit)).alias('earnings'),df1.start_date,df1.end_date)
df3 = df2.join(df, df.user_id==df2.user_id, how='leftanti').select(df2.user_id,df2.profit.alias('earnings'),f.lit(None).alias('start_date'),f.lit(None).alias('end_date'))
final_df = df.union(df3)
final_df.show()

+-------+--------+----------+----------+
|user_id|earnings|start_date|  end_date|
+-------+--------+----------+----------+
|      3|    30.0|2020-06-01|2020-06-10|
|      1|   110.0|2020-06-01|2020-06-10|
|      2|   220.0|2020-06-01|2020-06-10|
|      5|     500|      null|      null|
+-------+--------+----------+----------+

其他解决方案的替代方案(在
scala
中,但应在
pyspark
中使用,改动最小)- 加载提供的输入
val数据1=
"""
|用户id |收入|开始日期|结束日期
|1       | 10     | 2020-06-01 | 2020-06-10
|2       | 20     | 2020-06-01 | 2020-06-10
|3       | 30     | 2020-06-01 | 2020-06-10
“.stripMargin”
val stringDS1=data1.split(System.lineSeparator())
.map(\\\\\).map(\.replaceAll(“^[\t]+\\t]+$”,“).mkString(“,”)
.toSeq.toDS()
val df1=spark.read
.期权(“sep”、“、”)
.选项(“推断模式”、“真”)
.选项(“标题”、“正确”)
.选项(“空值”、“空值”)
.csv(stringDS1)
df1.显示(错误)
df1.printSchema()
/**
* +-------+--------+-------------------+-------------------+
*|用户id |收入|开始日期|结束日期||
* +-------+--------+-------------------+-------------------+
* |1      |10      |2020-06-01 00:00:00|2020-06-10 00:00:00|
* |2      |20      |2020-06-01 00:00:00|2020-06-10 00:00:00|
* |3      |30      |2020-06-01 00:00:00|2020-06-10 00:00:00|
* +-------+--------+-------------------+-------------------+
*
*根
*|--user_id:integer(nullable=true)
*|--收益:整数(nullable=true)
*|--开始日期:时间戳(nullable=true)
*|--结束日期:时间戳(nullable=true)
*/
val数据2=
"""
|用户id |利润
|1       | 100
|2       | 200
|5       | 500
“.stripMargin”
val stringDS2=data2.split(System.lineSeparator())
.map(\\\\\).map(\.replaceAll(“^[\t]+\\t]+$”,“).mkString(“,”)
.toSeq.toDS()
val df2=spark.read
.期权(“sep”、“、”)
.选项(“推断模式”、“真”)
.选项(“标题”、“正确”)
.选项(“空值”、“空值”)
.csv(stringDS2)
df2.显示(错误)
df2.printSchema()
/**
* +-------+------+
*|用户id |利润|
* +-------+------+
* |1      |100   |
* |2      |200   |
* |5      |500   |
* +-------+------+
*
*根
*|--user_id:integer(nullable=true)
*|--利润:整数(nullable=true)
*/
连接表并获取所述细节中的所需列
df1.createOrReplaceTempView(“上表”)
df2.createOrReplaceTempView(“新表格”)
val processedDF=spark.sql(
"""
|选择合并(p.user\u id,n.user\u id)作为用户id,
|(合并(收益,0)+合并(收益,0))作为收益,
|开始日期,
|结束日期
|从上一个表p完全外部联接p.user\U id=n.user\U id上的新表n
“.stripMargin)
processedDF.orderBy(“用户id”).show(false)
/**
* +-------+--------+-------------------+-------------------+
*|用户id |收入|开始日期|结束日期||
* +-------+--------+-------------------+-------------------+
* |1      |110     |2020-06-01 00:00:00|2020-06-10 00:00:00|
* |2      |220     |2020-06-01 00:00:00|2020-06-10 00:00:00|
* |3      |30      |2020-06-01 00:00:00|2020-06-10 00:00:00|
*| 5 | 500 |零|零|
* +-------+--------+-------------------+-------------------+
*/

完全没有使用连接和联合,但是@anky的方法看起来更干净
import pyspark.sql.functions as f

import pyspark.sql.functions as f

df = df1.join(df2, df1.user_id==df2.user_id, how='left').select(df1.user_id, (df1.earnings.cast('int')+f.when(df2.profit.cast('int').isNull(),0).otherwise(df2.profit)).alias('earnings'),df1.start_date,df1.end_date)
df3 = df2.join(df, df.user_id==df2.user_id, how='leftanti').select(df2.user_id,df2.profit.alias('earnings'),f.lit(None).alias('start_date'),f.lit(None).alias('end_date'))
final_df = df.union(df3)
final_df.show()

+-------+--------+----------+----------+
|user_id|earnings|start_date|  end_date|
+-------+--------+----------+----------+
|      3|    30.0|2020-06-01|2020-06-10|
|      1|   110.0|2020-06-01|2020-06-10|
|      2|   220.0|2020-06-01|2020-06-10|
|      5|     500|      null|      null|
+-------+--------+----------+----------+