【问题标题】:PySpark Exploding array<map<string,string>>PySpark 爆炸数组<map<string,string>>
【发布时间】:2021-12-09 12:44:34
【问题描述】:

我正在尝试以数组> 格式展开列。在 DataBricks 中使用 PySpark。 数据如下:

root
 |-- zipcode: string (nullable = true)
 |-- employment_status: array (nullable = true)
 |    |-- element: map (containsNull = true)
 |    |    |-- key: string
 |    |    |-- value: string (valueContainsNull = true)
sdf:pyspark.sql.dataframe.DataFrame
zipcode:string
employment_status:array
element:map
key:string
value:string


+-------+---------------------------------------------------------------------------------------------------------------------------------------------+
|zipcode|employment_status                                                                                                                            |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------+
|95678  |[[key -> Data, values -> [{x=Full-time, y=13348}, {x=Part-time, y=8918}, {x=No Earnings, y=9972}]]]|
|95679  |[[key -> Data, values -> [{x=Full-time, y=0}, {x=Part-time, y=29}, {x=No Earnings, y=0}]]]         |
|95680  |[[key -> Data, values -> [{x=Full-time, y=43}, {x=Part-time, y=0}, {x=No Earnings, y=71}]]]        |
|95681  |[[key -> Data, values -> [{x=Full-time, y=327}, {x=Part-time, y=265}, {x=No Earnings, y=278}]]]    |
|95682  |[[key -> Data, values -> [{x=Full-time, y=8534}, {x=Part-time, y=6436}, {x=No Earnings, y=8748}]]] |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------+

我可以毫不费力地爆炸并利用这些值

sdf2 = sdf.select(sdf.zipcode, explode(sdf.employment_status))
sdf3 = sdf2.select(sdf2.zipcode, explode(sdf2.col))
sdf4 = sdf3.filter(sdf3.value != "Data").select(sdf3.zipcode, sdf3.value)

结果如下:

sdf4:pyspark.sql.dataframe.DataFrame
zipcode:string
value:string

+-------+------------------------------------------------------------------------------------------------------------------+
|zipcode|value                                                                                                             |
+-------+------------------------------------------------------------------------------------------------------------------+
|95678  |[{x=Full-time, y=13348}, {x=Part-time, y=8918}, {x=No Earnings, y=9972}]|
|95679  |[{x=Full-time, y=0}, {x=Part-time, y=29}, {x=No Earnings, y=0}]         |
|95680  |[{x=Full-time, y=43}, {x=Part-time, y=0}, {x=No Earnings, y=71}]        |
|95681  |[{x=Full-time, y=327}, {x=Part-time, y=265}, {x=No Earnings, y=278}]    |
|95682  |[{x=Full-time, y=8534}, {x=Part-time, y=6436}, {x=No Earnings, y=8748}] |
+-------+------------------------------------------------------------------------------------------------------------------+

我有一个 F.regexp_extract 和 F.collect_list 的解决方案,但感觉不正确。 结果应该如下

+-------+-------------+-------------+------------+
|zipcode|full_employed|part_employed|non_employed|
+-------+-------------+-------------+------------+
|  95678|        13348|         8918|        9972|
|  95679|            0|           29|           0|
|  95680|           43|            0|          71|
|  95681|          327|          265|         691|
|  95682|         8534|         6436|        8748|
+-------+-------------+-------------+------------+

或者“全职”、“兼职”和“无收入”作为代号,你猜这无关紧要。

非常感谢任何想法! 谢谢!

【问题讨论】:

    标签: arrays dictionary pyspark explode


    【解决方案1】:

    这样的?

    from pyspark.sql import functions as F
    
    (sdf4
        .withColumn('y1', F.regexp_extract('value', 'y=([^}]+).*y=([^}]+).*y=([^}]+)', 1).cast('int'))
        .withColumn('y2', F.regexp_extract('value', 'y=([^}]+).*y=([^}]+).*y=([^}]+)', 2).cast('int'))
        .withColumn('y3', F.regexp_extract('value', 'y=([^}]+).*y=([^}]+).*y=([^}]+)', 3).cast('int'))
    
        .select('zipcode', F
            .expr('stack(1, y1, y2, y3)')
            .alias('full_employed','part_employed','non_employed')
        )
        .show()
    )
    
    # Output
    # +-------+-------------+-------------+------------+
    # |zipcode|full_employed|part_employed|non_employed|
    # +-------+-------------+-------------+------------+
    # |  95678|        13348|         8918|        9972|
    # |  95679|            0|           29|           0|
    # |  95680|           43|            0|          71|
    # |  95681|          327|          265|         278|
    # |  95682|         8534|         6436|        8748|
    # +-------+-------------+-------------+------------+
    

    【讨论】:

    • 你的输入df是什么样子的?就我而言,这只会产生“NULL”+--------+-------------+-------------+---- --------+ |邮编|全雇员|部分雇员|非雇员| +-------+-------------+-------------+------------+ |95678 |null |null |null | |95679 |null |null |null | |95680 |null |null |null | |95681 |null |null |null | |95682 |null |null |null | +-------+-------------+-------------+------------+
    • 这是我的 df 所拥有的:employment_status: array element: map key: string value: string 它正在寻找一个结构类型...
    • 我刚刚用示例输入更新了我的答案
    • 谢谢!不幸的是,我的数据看起来有点不同,只是添加到我的问题中。一旦我爆炸,我的映射就消失了,只剩下一个字符串。我可以将其拆分以获取数组/字符串,但随后我与之前使用正则表达式在同一轨道上从字符串中获取值...
    • 你能粘贴sdf.printSchema()的结果吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    相关资源
    最近更新 更多