繁体   English   中英

Scala/Spark:如何为列列表执行过滤器和更改列值?

[英]Scala/Spark : How to perform filter and change value of a column for a list of columns?

1)我有一个包含几列的 DF,但最重要的是“col1”、“col2”……“col10”(10 列)。 我只对其中至少一列的值 > 1 的行感兴趣。我现在拥有的是:

DF.filter(col(col1) > 1 or col(col2) > 1 or col(col3) > 1 or col(col4) > 1 or col(col5) > 1   
          or col(col6) > 1 or col(col7) > 1 or col(col8) > 1 or col(col9) > 1 or col(col10) > 1)

2) 与 #1 类似,我有另一个 DF,我需要将列列表的值减去 1

 DF
  .withColumn("col1", col("col1") - 1)
  .withColumn("col2", col("col2") - 1)
  .withColumn("col3", col("col3") - 1)
  .withColumn("col4", col("col4") - 1)
   // and so on ..... 

这些都可以工作,但是有没有更优雅的方式来处理多列?

您可以创建一个感兴趣的列的列表,并使用reduce来组装where子句中的重复or条件:

val df = Seq(
  (101, 0, -1, -2, -3, -4),
  (102, -1, 0, 1, 2, 3)
).toDF("id", "c1", "c2", "c3", "c4", "c5")

val colList = df.columns.filter(_.startsWith("c"))

df.where(colList.map(col(_) > 1).reduce(_ || _)).show
// +---+---+---+---+---+---+
// | id| c1| c2| c3| c4| c5|
// +---+---+---+---+---+---+
// |102| -1|  0|  1|  2|  3|
// +---+---+---+---+---+---+

对于重复的withColumn转换,请考虑使用foldLeft

colList.foldLeft(df)((acc, c) => acc.withColumn(c, col(c) - 1)).show
// +---+---+---+---+---+---+
// | id| c1| c2| c3| c4| c5|
// +---+---+---+---+---+---+
// |101| -1| -2| -3| -4| -5|
// |102| -2| -1|  0|  1|  2|
// +---+---+---+---+---+---+

但是,与使用重复的withColumn ,在一个转换中作为ArrayType列的元素跨列执行减法会更有效:

df.
  withColumn("arr", array(colList.map(col(_) - 1): _*)).
  select($"id" +: (0 until colList.size).map(i => $"arr"(i).as(colList(i))): _*)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM