Pyspark SQL:在数据透视表中保留只有空值的条目

Posted

技术标签:

【中文标题】Pyspark SQL:在数据透视表中保留只有空值的条目【英文标题】:Pyspark SQL: Keep entries with only null values in pivot table 【发布时间】:2018-01-27 17:19:17 【问题描述】:

我正在尝试在 PySpark SQL 数据帧上创建一个数据透视表,它不会删除空值。我的输入表结构如下:

我在 Python 2 和 spark 2.1 下运行 IBM Data Science Experience 云中的所有内容。

在 pandas 数据帧上执行此操作时,“dropna=false”参数给了我想要的结果。

table= pd.pivot_table(ratings,columns=['movieId'],index=[ 'monthyear','userId'], values='rating', dropna=False)

作为输出,我得到以下信息:

在 PySpark SQL 中,我目前正在使用以下命令:

ratings_pivot = spark_df.groupBy('monthyear','userId').pivot('movieId').sum("rating").show()

作为输出,我得到以下信息:

如您所见,没有显示所有只有空值的条目。是否有可能在 SQL 中使用类似 dropna=false 的东西?由于这是非常具体的,我在互联网上找不到任何相关信息。

我刚刚提取了一个小数据集进行复制:

df = spark.createDataFrame([("1", 30, 2.5,200912), ("1", 32, 3.0,200912), ("2", 40, 4.0,201002), ("3", 45, 2.5,200002)], ("userID", "movieID", "rating", "monthyear"))

df.show()

+------+-------+------+---------+
|userID|movieID|rating|monthyear|
+------+-------+------+---------+
|     1|     30|   2.5|   200912|
|     1|     32|   3.0|   200912|
|     2|     40|   4.0|   201002|
|     3|     45|   2.5|   200002|
+------+-------+------+---------+

如果我现在运行数据透视查询,我会得到以下结果:

df.groupBy("monthyear","UserID").pivot("movieID").sum("rating").show()

+---------+------+----+----+----+----+
|monthyear|UserID|  30|  32|  40|  45|
+---------+------+----+----+----+----+
|   201002|     2|null|null| 4.0|null|
|   200912|     1| 2.5| 3.0|null|null|
|   200002|     3|null|null|null| 2.5|
+---------+------+----+----+----+----+

我现在想要的是,结果如下所示:

+---------+------+----+----+----+----+
|monthyear|UserID|  30|  32|  40|  45|
+---------+------+----+----+----+----+
|   201002|     2|null|null| 4.0|null|
|   200912|     2|null|null|null|null|
|   200002|     2|null|null|null|null|
|   200912|     1| 2.5| 3.0|null|null|
|   200002|     1|null|null|null|null|
|   201002|     1|null|null|null|null|
|   200002|     3|null|null|null| 2.5|
|   200912|     3|null|null|null|null|
|   201002|     3|null|null|null|null|
+---------+------+----+----+----+----+

【问题讨论】:

感谢您的提示,我编辑了我的问题以使其可重现。 【参考方案1】:

Spark 提供了类似的功能,因为它无法扩展。 pivot 一个人就够贵了。可以通过外部连接手动完成:

n = 20 # Adjust value depending on the data

wide = (df
    # Get unique months
    .select("monthyear")
    .distinct()
    .coalesce(n)  # Coalesce to avoid partition number "explosion"
    # Same as above for UserID and get Cartesian product
    .crossJoin(df.select("UserID").distinct().coalesce(n))
    # Join with pivoted data
    .join(
        df.groupBy("monthyear", "UserID")
            .pivot("movieID")
            .sum("rating"),
        ["monthyear", "UserID"], 
        "leftouter"))
wide.show()

# +---------+------+----+----+----+----+
# |monthyear|UserID|  30|  32|  40|  45|
# +---------+------+----+----+----+----+
# |   201002|     3|null|null|null|null|
# |   201002|     2|null|null| 4.0|null|
# |   200002|     1|null|null|null|null|
# |   200912|     1| 2.5| 3.0|null|null|
# |   200002|     3|null|null|null| 2.5|
# |   200912|     2|null|null|null|null|
# |   200912|     3|null|null|null|null|
# |   201002|     1|null|null|null|null|
# |   200002|     2|null|null|null|null|
# +---------+------+----+----+----+----+

【讨论】:

非常好。非常感谢!这正是我想要的。【参考方案2】:

Spark 确实为行和列保留了所有 null 值的条目:

Spark 2.1

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.1.1
      /_/

Using Python version 3.6.4 (default, Dec 21 2017 21:42:08)
SparkSession available as 'spark'.

In [1]: df = spark.createDataFrame([("a", 1, 4), ("a", 2, 2), ("b", 3, None), (None, 4, None)], ("x", "y", "z"))

In [2]: df.groupBy("x").pivot("y").sum("z").show()
+----+----+----+----+----+                                                      
|   x|   1|   2|   3|   4|
+----+----+----+----+----+
|null|null|null|null|null|
|   b|null|null|null|null|
|   a|   4|   2|null|null|
+----+----+----+----+----+

Spark 2.2

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.2.1
      /_/

Using Python version 3.6.4 (default, Dec 21 2017 21:42:08)
SparkSession available as 'spark'.

In [1]: df = spark.createDataFrame([("a", 1, 4), ("a", 2, 2), ("b", 3, None), (None, 4, None)], ("x", "y", "z"))

In [2]: df.groupBy("x").pivot("y").sum("z").show()
+----+----+----+----+----+                                                      
|   x|   1|   2|   3|   4|
+----+----+----+----+----+
|null|null|null|null|null|
|   b|null|null|null|null|
|   a|   4|   2|null|null|
+----+----+----+----+----+

Spark 2.3

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.3.0
      /_/

Using Python version 3.6.4 (default, Dec 21 2017 21:42:08)
SparkSession available as 'spark'.

In [1]: df = spark.createDataFrame([("a", 1, 4), ("a", 2, 2), ("b", 3, None), (None, 4, None)], ("x", "y", "z"))

In [2]: df.groupBy("x").pivot("y").sum("z").show()
+----+----+----+----+----+                                                      
|   x|   1|   2|   3|   4|
+----+----+----+----+----+
|null|null|null|null|null|
|   b|null|null|null|null|
|   a|   4|   2|null|null|
+----+----+----+----+----+

【讨论】:

非常感谢您的回答。我正在使用 Spark 2.1 版。我在最后一部分编辑了我的问题以使其更清楚。

以上是关于Pyspark SQL:在数据透视表中保留只有空值的条目的主要内容,如果未能解决你的问题,请参考以下文章

SqlServer中的数据根据该表中某字段的值的结果决定是不是显示

删除一张表中重复数据并保留一条ID最小的记录

php sql中带有日期、变量类别和总和值的数据透视表

分解表以在列中进行透视(SQL,PYSPARK)

从 SQL Server DB 更新单独工作表中的数据后自动刷新 Excel 2007 数据透视表

SQL,表中字段的某个范围内插入相同数据