Pyspark:reduceByKey多列但独立

时间:2018-01-27 18:27:43

标签: apache-spark pyspark

我的数据由多列组成,看起来像这样:

enter image description here

我想分别对每列的数据进行分组,并计算每个元素的出现次数,我可以通过这样做来实现:

df.groupBy("Col-1").count() 

df.groupBy("Col-2").count()

df.groupBy("Col-n").count()

但是,如果有1000列,那我就很耗时。所以我试图找到另一种方法:

到目前为止我所做的一切:

def mapFxn1(x):
    vals=[1] * len(x)
    c=tuple(zip(list(x), vals))
    return c

df_map=df.rdd.map(lambda x: mapFxn1(x))

mapFxn1获取每一行并将其转换为元组的元组:所以基本上第一行看起来像这样:((10,1),(2,1),(x,1))

我只是想知道如何使用lambda x,y:x + y在df_map上使用reduceByKey,以便在每个列上实现分组并在单个步骤中计算每个列中元素的出现次数。

提前谢谢

1 个答案:

答案 0 :(得分:0)

使用cube

df = spark.createDataFrame(
    [(3, 2), (2, 1), (3, 8), (3, 9), (4, 1)]
).toDF("col1", "col2")
df.createOrReplaceTempView("df")

spark.sql("""SELECT col1, col2, COUNT(*) 
             FROM df GROUP BY col1, col2 GROUPING SETS(col1, col2)"""
).show()

# +----+----+--------+
# |col1|col2|count(1)|
# +----+----+--------+
# |null|   9|       1|
# |   3|null|       3|
# |null|   1|       2|
# |null|   2|       1|
# |   2|null|       1|
# |null|   8|       1|
# |   4|null|       1|
# +----+----+--------+

使用melt

melt(df, [], df.columns).groupBy("variable", "value").count().show()

# +--------+-----+-----+
# |variable|value|count|
# +--------+-----+-----+
# |    col2|    8|    1|
# |    col1|    3|    3|
# |    col2|    2|    1|
# |    col1|    2|    1|
# |    col2|    9|    1|
# |    col1|    4|    1|
# |    col2|    1|    2|
# +--------+-----+-----+

使用reduceByKey

from operator import add

counts = (df.rdd
   .flatMap(lambda x: x.asDict().items())
   .map(lambda x: (x, 1))
   .reduceByKey(add))

counts.toLocalIterator():
    print(x)
#     
# (('col1', 2), 1)
# (('col2', 8), 1)
# (('col2', 1), 2)
# (('col2', 9), 1)
# (('col1', 4), 1)
# (('col1', 3), 3)
# (('col2', 2), 1)