在列的数量或名称未知的情况下,如何同时统计多个列中不同值的出现次数



我有一个自动生成的数据帧,列的名称和编号永远不会为人所知。我想知道如何计算每个列中每个值的出现次数。

例如,

Col1  Col2   Col3
Row1    True  False  False
Row2    True  True   True
Row3    False False  True
Row4    False False  False

结果应该是:

Col1 Count Col2 Count Col3 Count
True   2   True    1  True   2
False  2   False   3  False  2

我试过像这样应用GroupBy:

df.groupBy(record => (record.Col1, record.Col2, record.Col3)).count().show

但这对我来说不起作用,因为我不知道列的编号或名称。

试试这个-

加载提供的测试数据

val data =
"""
|Col1  Col2   Col3
|True  False  False
|True  True   True
|False False  True
|False False  False
""".stripMargin
val stringDS2 = data.split(System.lineSeparator())
.map(_.split("\s+").map(_.replaceAll("""^[ t]+|[ t]+$""", "")).mkString("|"))
.toSeq.toDS()
val df2 = spark.read
.option("sep", "|")
.option("inferSchema", "true")
.option("header", "true")
.option("nullValue", "null")
.csv(stringDS2)
df2.show(false)
df2.printSchema()
/**
* +-----+-----+-----+
* |Col1 |Col2 |Col3 |
* +-----+-----+-----+
* |true |false|false|
* |true |true |true |
* |false|false|true |
* |false|false|false|
* +-----+-----+-----+
*
* root
* |-- Col1: boolean (nullable = true)
* |-- Col2: boolean (nullable = true)
* |-- Col3: boolean (nullable = true)
*/

计算列中每个不同值计数的简单方法

val findCounts = df2.columns.flatMap(c => Seq(col(c), count(c).over(Window.partitionBy(c)).as(s"count_$c")))
df2.select(findCounts: _*).distinct()
.show(false)
/**
* +-----+----------+-----+----------+-----+----------+
* |Col1 |count_Col1|Col2 |count_Col2|Col3 |count_Col3|
* +-----+----------+-----+----------+-----+----------+
* |false|2         |false|3         |false|2         |
* |false|2         |false|3         |true |2         |
* |true |2         |false|3         |false|2         |
* |true |2         |true |1         |true |2         |
* +-----+----------+-----+----------+-----+----------+
*/

如果您需要与上述格式相同的格式,请尝试

假设数据帧中的所有列都具有相同的不同值

// Assuming all the columns in the dataframe have same distinct values
val columns = df2.columns
val head = columns.head
val zeroDF = df2.groupBy(head).agg(count(head).as(s"${head}_count"))
columns.tail.foldLeft(zeroDF){
(df, c) => df.join(df2.groupBy(c).agg(count(c).as(s"${c}_count")), col(head) === col(c))
}.show(false)
/**
* +-----+----------+-----+----------+-----+----------+
* |Col1 |Col1_count|Col2 |Col2_count|Col3 |Col3_count|
* +-----+----------+-----+----------+-----+----------+
* |false|2         |false|3         |false|2         |
* |true |2         |true |1         |true |2         |
* +-----+----------+-----+----------+-----+----------+
*/

最新更新