按 PySpark 中不同的子 ArrayType 元素计数
Counting by distinct sub-ArrayType elements in PySpark
我有以下 JSON 结构:
{
"stuff": 1, "some_str": "srt", list_of_stuff": [
{"element_x":1, "element_y":"22x"},
{"element_x":3, "element_y":"23x"}
]
},
{
"stuff": 2, "some_str": "srt2", "list_of_stuff": [
{"element_x":1, "element_y":"22x"},
{"element_x":4, "element_y":"24x"}
]
},
当我将它读入 PySpark DataFrame 时 json:
import pyspark.sql
import json
from pyspark.sql import functions as F
from pyspark.sql.types import *
schema = StructType([
StructField("stuff", IntegerType()),
StructField("some_str", StringType()),
StructField("list_of_stuff", ArrayType(
StructType([
StructField("element_x", IntegerType()),
StructField("element_y", StringType()),
])
))
])
df = spark.read.json("hdfs:///path/file.json/*", schema=schema)
df.show()
我得到以下信息:
+--------+---------+-------------------+
| stuff | some_str| list_of_stuff |
+--------+---------+-------------------+
| 1 | srt | [1,22x], [3,23x] |
| 2 | srt2 | [1,22x], [4,24x] |
+--------+---------+-------------------+
PySpark 似乎扁平化了 ArrayType 的键名称,尽管我在这样做时仍然可以看到它们 df.printSchema()
:
root
|-- stuff: integer (nullable = true)
|-- some_str: string (nullable = true)
|-- list_of_stuff: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- element_x: integer (nullable = true)
| | |-- element_y: string (nullable = true)
问题:
我需要计算 element_y
在我的 DataFrame 中出现的不同次数。所以给出示例 JSON,我会得到这个输出:
22x: 2, 23x: 1, 24x :1
我不确定如何进入 ArrayType 并计算子元素的不同值 element_y
。任何帮助表示赞赏。
一种方法是使用 rdd
、flatten
数组和 flatMap
,然后计数:
df.rdd.flatMap(lambda r: [x.element_y for x in r['list_of_stuff']]).countByValue()
# defaultdict(<class 'int'>, {'24x': 1, '22x': 2, '23x': 1})
或者使用数据框,先explode
列,然后你可以在每个数组中访问element_y
; groupBy
element_y
,然后 count
应该给出您需要的结果:
import pyspark.sql.functions as F
(df.select(F.explode(df.list_of_stuff).alias('stuff'))
.groupBy(F.col('stuff').element_y.alias('key'))
.count()
.show())
+---+-----+
|key|count|
+---+-----+
|24x| 1|
|22x| 2|
|23x| 1|
+---+-----+
我有以下 JSON 结构:
{
"stuff": 1, "some_str": "srt", list_of_stuff": [
{"element_x":1, "element_y":"22x"},
{"element_x":3, "element_y":"23x"}
]
},
{
"stuff": 2, "some_str": "srt2", "list_of_stuff": [
{"element_x":1, "element_y":"22x"},
{"element_x":4, "element_y":"24x"}
]
},
当我将它读入 PySpark DataFrame 时 json:
import pyspark.sql
import json
from pyspark.sql import functions as F
from pyspark.sql.types import *
schema = StructType([
StructField("stuff", IntegerType()),
StructField("some_str", StringType()),
StructField("list_of_stuff", ArrayType(
StructType([
StructField("element_x", IntegerType()),
StructField("element_y", StringType()),
])
))
])
df = spark.read.json("hdfs:///path/file.json/*", schema=schema)
df.show()
我得到以下信息:
+--------+---------+-------------------+
| stuff | some_str| list_of_stuff |
+--------+---------+-------------------+
| 1 | srt | [1,22x], [3,23x] |
| 2 | srt2 | [1,22x], [4,24x] |
+--------+---------+-------------------+
PySpark 似乎扁平化了 ArrayType 的键名称,尽管我在这样做时仍然可以看到它们 df.printSchema()
:
root
|-- stuff: integer (nullable = true)
|-- some_str: string (nullable = true)
|-- list_of_stuff: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- element_x: integer (nullable = true)
| | |-- element_y: string (nullable = true)
问题:
我需要计算 element_y
在我的 DataFrame 中出现的不同次数。所以给出示例 JSON,我会得到这个输出:
22x: 2, 23x: 1, 24x :1
我不确定如何进入 ArrayType 并计算子元素的不同值 element_y
。任何帮助表示赞赏。
一种方法是使用 rdd
、flatten
数组和 flatMap
,然后计数:
df.rdd.flatMap(lambda r: [x.element_y for x in r['list_of_stuff']]).countByValue()
# defaultdict(<class 'int'>, {'24x': 1, '22x': 2, '23x': 1})
或者使用数据框,先explode
列,然后你可以在每个数组中访问element_y
; groupBy
element_y
,然后 count
应该给出您需要的结果:
import pyspark.sql.functions as F
(df.select(F.explode(df.list_of_stuff).alias('stuff'))
.groupBy(F.col('stuff').element_y.alias('key'))
.count()
.show())
+---+-----+
|key|count|
+---+-----+
|24x| 1|
|22x| 2|
|23x| 1|
+---+-----+