我一直在绞尽脑汁,我正在尝试执行以下操作。本质上,我有两个数据框,一个来自昨天,一个来自今天,这里今天只是一个增量(即仅新行)。我想将这两部分合并在一起,以便更新新行,并继续使用旧行。
sc = SparkContext.getOrCreate()
old = sc.parallelize([
{"id": 1, "value": 10, "date": "yesterday"},
{"id": 2, "value": 20, "date": "yesterday", "foo": "bar"},
{"id": 3, "value": 30, "date": "yesterday"}
]).toDF()
new = sc.parallelize([
{"id": 2, "value": 25, "date": "today"},
{"id": 4, "value": 45, "date": "today"}
]).toDF()
expected = sc.parallelize([
{"id": 1, "value": 10, "date": "yesterday"},
{"id": 2, "value": 25, "date": "today"},
{"id": 3, "value": 30, "date": "yesterday"},
{"id": 4, "value": 45, "date": "today"},
]).toDF()
# something to merge old and new ...?
在纯python中,我只会使用:
old = {"a": 10, "b": 20, "c": 30 }
new = {"b": 25, "d": 45}
expected = {"a": 10, "b": 25, "c": 30, "d": 45 }
calculated = {**old, **new}
执行此操作的“正确”方法是什么?也许同时参加/推销?
编辑: 如前所述,这个问题是下面链接的重复。但是,该示例显示了针对非常具体的列名称的非常手动编码的查询。
我需要在大约5个数据帧中重用此代码,每个数据帧有20多个列,如果不需要,我不想针对列名对合并步骤进行硬编码;模式仍在变化。
在pyspark / spark中确实没有加入/合并功能吗?我有一个可以使用left_anti和union的解决方案,但是由于某种原因,它闻起来很不对劲。
答案 0 :(得分:0)
我认为最简单的方法就是使用union
和groupby
和first
函数。
旧df:
+---+-----+---------+
| id|value| date|
+---+-----+---------+
| 1| 10|yesterday|
| 2| 20|yesterday|
| 3| 30|yesterday|
+---+-----+---------+
新df:
+---+-----+---------+
| id|value| date|
+---+-----+---------+
| 2| 25| today|
| 4| 45| today|
+---+-----+---------+
下面的代码合并两个数据框:
import pyspark.sql.functions as f
unionDF = old.union(new).sort("date")
unionDF.show()
联盟df:
+---+-----+---------+
| id|value| date|
+---+-----+---------+
| 2| 25| today|
| 4| 45| today|
| 1| 10|yesterday|
| 2| 20|yesterday|
| 3| 30|yesterday|
+---+-----+---------+
最后一步,groupby
和first
函数:
firstCols = [f.first(col).alias(str(col)) for col in unionDF.columns[1:]]
finalDF = unionDF.groupby("id").agg(*firstCols).sort("id")
finalDF.show()
最终df:
+---+-----+---------+
| id|value| date|
+---+-----+---------+
| 1| 10|yesterday|
| 2| 25| today|
| 3| 30|yesterday|
| 4| 45| today|
+---+-----+---------+