pyspark制作新数据帧的有效方法是什么?

pyspark制作新数据帧的有效方法是什么?,pyspark,spark-dataframe,memory-efficient,Pyspark,Spark Dataframe,Memory Efficient,我有一个数据帧,如: +---------------+-------+ | date | ID | count | +--------+------+-------+ |20170101| 258 | 1003 | |20170102| 258 | 13 | |20170103| 258 | 1 | |20170104| 258 | 108 | |20170109| 258 | 25 | | ... | ... | ... | |2017

我有一个数据帧,如:

+---------------+-------+
|  date  |  ID  | count |
+--------+------+-------+
|20170101| 258  |  1003 |
|20170102| 258  |  13   |
|20170103| 258  |  1    |
|20170104| 258  |  108  |
|20170109| 258  |  25   |
|  ...   | ...  |  ...  |
|20170101| 2813 |  503  |
|20170102| 2813 |  139  |
|  ...   | ...  |  ...  |
|20170101| 4963 |  821  |
|20170102| 4963 |  450  |
|  ...   | ...  |  ...  |
+--------+------+-------+
在我的数据框中,没有一些数据

例如,这里缺少ID
258
的日期
20170105
~
20170108

缺少数据意味着不出现(=计数==0)

但我想添加计数也为0的数据,如下所示:

+---------------+-------+
|  date  |  ID  | count |
+--------+------+-------+
|20170101| 258  |  1003 |
|20170102| 258  |  13   |
|20170103| 258  |  1    |
|20170104| 258  |  108  |
|20170105| 258  |  0    |
|20170106| 258  |  0    |
|20170107| 258  |  0    |
|20170108| 258  |  0    |
|20170109| 258  |  25   |
|  ...   | ...  |  ...  |
|20170101| 2813 |  503  |
|20170102| 2813 |  139  |
|  ...   | ...  |  ...  |
|20170101| 4963 |  821  |
|20170102| 4963 |  450  |
|  ...   | ...  |  ...  |
+--------+------+-------+
dataframe是不可变的,所以如果我想向这个dataframe添加零计数的数据, 必须创建一个新的数据帧

但是,即使我有一个持续时间(20170101~20171231)和ID列表,我也不能使用
for loop
到数据帧

如何创建新的数据帧

我已经尝试过的是制作一个正确的数据帧,然后比较两个数据帧,再制作一个只有0个计数数据的数据帧。最后合并“原始数据帧”和“0计数数据帧”。我认为这不是一个好的、漫长的过程。请给我推荐一些其他有效的解决方案。

希望这有帮助

from pyspark.sql.functions导入unix\u时间戳、from\u unixtime、struct、datediff、lead、col、explode、lit、udf
从pyspark.sql.window导入窗口
从pyspark.sql.types导入ArrayType、DateType
从日期时间导入时间增量
#样本数据
df=sc.parallelize([
['20170101', 258, 1003],
['20170102', 258, 13],
['20170103', 258, 1],
['20170104', 258, 108],
['20170109', 258, 25],
['20170101', 2813, 503],
['20170102', 2813, 139],
['20170101', 4963, 821],
['20170102', 4963, 450]]).\
toDF((‘日期’、‘ID’、‘计数’)\
withColumn(“日期”,from_unixtime(unix_timestamp('date','yyyyymmdd')).cast('date'))
df.show()
定义日期列表fn(d):
对于范围(1,d[1])内的x,返回[d[0]+timedelta(天数=x)]
date\u list\u udf=udf(date\u list\u fn,数组类型(DateType())
w=Window.partitionBy('ID')。orderBy('date'))
#缺少日期的数据帧
df_missing=df.with column(“diff”,datediff(lead('date'))。超过(w),'date'))\
过滤器(col(“diff”)>1)\
带列(“日期列表”,日期列表,自定义项(结构(“日期”,“差异”))\
withColumn(“日期列表”),explode(col(“日期列表”))\
选择(列(“日期列表”)。别名(“日期”),“ID”,lit(0)。别名(“计数”))
#通过将样本数据与缺失的日期数据框相结合,生成最终数据框
final_df=df.union(df_缺失).sort(col(“ID”)、col(“date”))
最终设计图显示()
样本数据:

+----------+----+-----+
|      date|  ID|count|
+----------+----+-----+
|2017-01-01| 258| 1003|
|2017-01-02| 258|   13|
|2017-01-03| 258|    1|
|2017-01-04| 258|  108|
|2017-01-09| 258|   25|
|2017-01-01|2813|  503|
|2017-01-02|2813|  139|
|2017-01-01|4963|  821|
|2017-01-02|4963|  450|
+----------+----+-----+
输出为:

+----------+----+-----+
|      date|  ID|count|
+----------+----+-----+
|2017-01-01| 258| 1003|
|2017-01-02| 258|   13|
|2017-01-03| 258|    1|
|2017-01-04| 258|  108|
|2017-01-05| 258|    0|
|2017-01-06| 258|    0|
|2017-01-07| 258|    0|
|2017-01-08| 258|    0|
|2017-01-09| 258|   25|
|2017-01-01|2813|  503|
|2017-01-02|2813|  139|
|2017-01-01|4963|  821|
|2017-01-02|4963|  450|
+----------+----+-----+