PySpark - 将多行客户“压缩”成一行,删除空白

Posted

技术标签:

【中文标题】PySpark - 将多行客户“压缩”成一行,删除空白【英文标题】:PySpark - "compressing" multiple-row customers into one row, deleting blanks 【发布时间】:2018-07-11 11:40:36 【问题描述】:

所以我目前有一个如下所示的数据框:

+-------------+----------------+---------------+------------------+-----------------+
| customer_id | init_base_date | init_end_date | reinit_base_date | reinit_end_date |
+-------------+----------------+---------------+------------------+-----------------+
| ...         |                |               |                  |                 |
| A           | 2015-07-30     |               |                  |                 |
| A           |                | 2016-07-24    |                  |                 |
| B           | 2015-07-10     |               |                  |                 |
| B           |                | 2015-10-05    |                  |                 |
| B           |                |               | 2016-01-09       |                 |
| B           |                |               |                  | 2016-07-04      |
| C           | 2015-05-13     |               |                  |                 |
| C           |                | 2015-08-09    |                  |                 |
| ...         |                |               |                  |                 |
+-------------+----------------+---------------+------------------+-----------------+

我真的需要把它转换成表格:

+-------------+----------------+---------------+------------------+-----------------+
| customer_id | init_base_date | init_end_date | reinit_base_date | reinit_end_date |
+-------------+----------------+---------------+------------------+-----------------+
| ...         |                |               |                  |                 |
| A           | 2015-07-30     | 2016-07-24    |                  |                 |
| B           | 2015-07-10     | 2015-10-05    | 2016-01-09       | 2016-07-04      |
| C           | 2015-05-13     | 2015-08-09    |                  |                 |
| ...         |                |               |                  |                 |
+-------------+----------------+---------------+------------------+-----------------+

我可以想到几种非常乏味的方法来完成上述操作,但我想知道是否有一种快速有效的方法(也许使用 windows?我现在才使用 PySpark 一个月,所以绝对还是一个新手)。

【问题讨论】:

请阅读How to make good reproducible Apache Spark Dataframe examples和edit你的问题。 【参考方案1】:

如果您显示的那些空单元格实际上是nulls(而不是空字符串),您可以使用pyspark.sql.functions.first() 作为groupBy 中的聚合函数。关键是将first()ignorenulls参数设置为True(默认为False)。

import pyspark.sql.functions as f
cols = [c for c in df.columns if c != 'customer_id']
df.groupBy('customer_id').agg(*[f.first(c, True).alias(c) for c in cols]).show()
#+-----------+--------------+-------------+----------------+---------------+
#|customer_id|init_base_date|init_end_date|reinit_base_date|reinit_end_date|
#+-----------+--------------+-------------+----------------+---------------+
#|          A|    2015-07-30|   2016-07-24|            null|           null|
#|          B|    2015-07-10|   2015-10-05|      2016-01-09|     2016-07-04|
#|          C|    2015-05-13|   2015-08-09|            null|           null|
#+-----------+--------------+-------------+----------------+---------------+

如果这些空白值实际上是空字符串,您可以先replace all empty strings with null 并按照上面的方法。然后,您可以(可选)将 null 值替换为空格。

from functools import reduce  # for python3
cols = [c for c in df.columns if c != 'customer_id']
df = reduce(lambda df, c: df.withColumn(c, f.when(f.col(c) != '', f.col(c))), cols, df)
df = df.groupBy('customer_id').agg(*[f.first(c, True).alias(c) for c in cols])
df.na.fill('').show()  # fill nulls with blanks
#+-----------+--------------+-------------+----------------+---------------+
#|customer_id|init_base_date|init_end_date|reinit_base_date|reinit_end_date|
#+-----------+--------------+-------------+----------------+---------------+
#|          A|    2015-07-30|   2016-07-24|                |               |
#|          B|    2015-07-10|   2015-10-05|      2016-01-09|     2016-07-04|
#|          C|    2015-05-13|   2015-08-09|                |               |
#+-----------+--------------+-------------+----------------+---------------+

【讨论】:

以上是关于PySpark - 将多行客户“压缩”成一行,删除空白的主要内容,如果未能解决你的问题,请参考以下文章

将一行拆分为多行pyspark

如何将共享 id 的多行合并为一行(PYSPARK)

将多行的单元格连接成一行

连接多行 Pyspark

pyspark groupby 使用 String groupby 键在输出中生成多行

如何将多行单元格数据转变成一行?这个Excel技巧你一定不知道!