Pandas PySpark:Concat两个具有列和的数据帧
我有两个PySpark数据帧,我想留下来加入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
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|
+-------+--------+----------+----------+