【问题标题】:merge rows in a dataframe by id trying to avoid null values in columns (Spark scala)通过 id 合并数据框中的行,试图避免列中的空值(Spark scala)
【发布时间】:2021-09-22 20:18:32
【问题描述】:

我正在使用 Spark scala 进行开发,我想合并数据框中的一些行...

我的数据框是下一个:

+-------------------------+-------------------+---------------+------------------------------+
|name                     |col1               |col2           |col3                          |
+-------------------------+-------------------+---------------+------------------------------+
|                    a    |               null|           null|                      0.000000|
|                    a    |           0.000000|           null|                          null|
|                    b    |               null|           null|                      0.000000|
|                    b    |         300.000000|           null|                          null|
+-------------------------+-------------------+---------------+------------------------------+

我想开启下一个数据框:

+-------------------------+-------------------+---------------+------------------------------+
|name                     |col1               |col2           |col3                          |
+-------------------------+-------------------+---------------+------------------------------+
|                    a    |           0.000000|           null|                      0.000000|
|                    b    |         300.000000|           null|                      0.000000|
+-------------------------+-------------------+---------------+------------------------------+

考虑到:

-某些列的所有值都可以为空。

-一个数据框中可以有很多列。


据我所知,我必须将 groupBy 与 agg() 一起使用,但我无法获得正确的表达式:

df.groupBy("name").agg()

【问题讨论】:

    标签: scala dataframe apache-spark row


    【解决方案1】:

    如果“合并”表示求和,则可以从数据框架构中接收列列表并包含在“聚合”中:

    val df = Seq(
      ("a", Option.empty[Double], Option.empty[Double], Some(0.000000)),
      ("a", Some(0.000000), Option.empty[Double], Option.empty[Double]),
      ("b", Option.empty[Double], Option.empty[Double], Some(0.000000)),
      ("b", Some(300.000000), Option.empty[Double], Option.empty[Double])
    ).toDF(
      "name", "col1", "col2", "col3"
    )
    val columnsToMerge = df
      .columns
      .filterNot(_ == "name")
      .map(c => sum(c).alias(c))
    
    df.groupBy("name")
      .agg(columnsToMerge.head, columnsToMerge.tail: _*)
    

    结果:

    +----+-----+----+----+
    |name|col1 |col2|col3|
    +----+-----+----+----+
    |a   |0.0  |null|0.0 |
    |b   |300.0|null|0.0 |
    +----+-----+----+----+
    

    【讨论】:

      【解决方案2】:
      • 您可以按照您的建议使用groupby('name'),然后使用ffill() + bfill()
      df = df.groupby('name').ffill().bfill().drop_duplicates(keep='first')
      
      df.update(df.groupby('name').ffill().bfill())
      df.drop_duplicates(keep='first', inplace=True)
      

      结果df:

      name col1 col2 col3
      a 0 0
      b 300 0

      【讨论】:

      • 感谢您的快速回复。我在scala中尝试这个,而不是在python中。无论如何,我会用类似的方法。非常感谢!
      猜你喜欢
      • 2017-11-03
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-07
      相关资源
      最近更新 更多