按列列出的前n个元素

rn0zuynd  于 2021-06-24  发布在  Hive
关注(0)|答案(1)|浏览(318)

假设我有一个sparkDataframe:

col1 | col2 | col3 | col4
   a |    g |    h |    p
   r |    i |    h |    l
   f |    j |    z |    d
   a |    j |    m |    l
   f |    g |    h |    q
   f |    z |    z |    a
 ...

我想取消对列的拆分,并按出现次数获得前n个元素的数组。例如,n=3:

columnName |   content
      col1 | [f, a, r]
      col2 | [g, j, i]
      col3 | [h, z, m]
      col4 | [l, a, d]

我用以下代码将列名连接到一个列中:

columnNames = output_df.columns
output_df = output_df.withColumn("columns", F.array([F.lit(x) for x in columnNames]))

我想我可以使用explode函数,但不确定它是否是最有效的方法。
有什么建议吗?
谢谢

r3i60tvu

r3i60tvu1#

我没有看到任何其他方式,除非通过手动计算所有发生,这是不是真的有效,我很高兴听到其他方法。
但是,如果您不担心性能问题,这就可以了!
请注意,我是用scala编写的,我将尝试将其翻译为pyspark,但由于我以前从未这样做过,这将是困难的。

// Let's create a dataframe for reproductibility
val data = Seq(("a", "g", "h", "p"),
("r", "i", "h", "l"),
("f", "j", "z", "d"),
("a", "j", "m", "l"),
("f", "g", "h", "q"),
("f", "z", "z", "a"))

val df = data.toDF("col1", "col2", "col3", "col4")

// Let's add a constant 1, with the groupby sum that will give us the occurencies !
val dfWithFuturOccurences = df.withColumn("futur_occurences", F.lit(1))

// Your n value
val n = 3

// Here goes the magic
df.columns // For each column
    .map(x => 
        (x, dfWithFuturOccurences
            .groupBy(x)
            .agg(sum("futur_occurences").alias("occurences")) // Count occurences here
            .orderBy(desc("occurences"))
            .select(x)
            .limit(n) // Select the top n elements
            .rdd.map(r => r(0).toString).collect().toSeq) //  Collect them and store them as a Seq of string
        )
    .toSeq
    .toDF("col", "top_elements")

在Pypark中,可能是这样的:

import pyspark.sql.functions as F

data = list(map(lambda x: 
            (x,
            [str(row[x]) for row in 
             dfWithFuturOccurences
            .groupBy(x)
            .agg(F.sum("futur_occurences").alias("occurences"))
            .orderBy(desc("occurences"))
            .select(x)
            .limit(n)
            .collect()]
            )
        , df.columns))

然后把你的数据转换成一个Dataframe就完成了!
输出:

+----+------------+
| col|top_elements|
+----+------------+
|col1|   [f, a, r]|
|col2|   [g, j, z]|
|col3|   [h, z, m]|
|col4|   [l, p, d]|
+----+------------+

相关问题