【问题标题】:Applying withColumn only when column exists in the dataframe仅当数据框中存在列时才应用 withColumn
【发布时间】:2020-08-20 07:04:41
【问题描述】:

我在 Java 8 中使用 spark-sql-2.4.1v。我有一个场景,我会将列名作为 list/Seq 传递,对于这些列,我只需要执行某些操作,例如 sum、avg、百分比等。

在我的场景中,假设我有 column1、column2、column3 列。第一次我将传递 column1 名称。

将拉取/选择“column1”数据并基于“column1”执行一些操作。第二次我将传递 column2 名称,但这次没有拉出较早的 column1,因此我的数据集不包含“column1”,因此较早的条件因错误“AnalysisException: cannot resolve 'column1' given input columns”而中断。

因此我需要检查列,如果存在某些列,则只执行与该列相关的操作,否则忽略这些操作。

如何在 Spark 中做到这一点?

数据库中的样本数据。

val data = List(
  ("20", "score", "school", "2018-03-31", 14 , 12 , 20),
  ("21", "score", "school", "2018-03-31", 13 , 13 , 21),
  ("22", "rate", "school", "2018-03-31", 11 , 14, 22),
  ("21", "rate", "school", "2018-03-31", 13 , 12, 23)
 )
    val df = data.toDF("id", "code", "entity", "date", "column1", "column2" ,"column3")
.select("id", "code", "entity", "date", "column2") /// these are passed for each run....this set will keep changing.



  Dataset<Row> enrichedDs = df
             .withColumn("column1_org",col("column1"))
             .withColumn("column1",
                     when(col("column1").isNotNull() , functions.callUDF("lookUpData",col("column1").cast(DataTypes.StringType)))
                  );

上述逻辑仅适用于选择列中“column1”可用的情况。这在第二组中失败,因为未选择“column1”,所以我需要了解为什么这仅适用于选择的列作为“column1”可用时。我需要一些逻辑来实现这一点。

【问题讨论】:

  • 无法理解拉取列数据的含义。你的测试用例是什么,出了什么问题?
  • @Lamanus 我的数据在数据库表中,这里的意思是选择这些数据......我的选择不是盲目选择......每次选择列都会不同......但是逻辑non-select columns code logic will be these ....when select set one columns ...set two column logic failing as those columns are not selected...my concern before executing logic need to check if those columns there in dataframe else跳过那些基于列的逻辑...如果您需要更多详细信息,请告诉我

标签: dataframe apache-spark apache-spark-sql


【解决方案1】:

检查这是否有帮助-

you can filter out columns, and process only valid columns

df.show(false)
    /**
      * +---+-----+------+----------+-------+-------+-------+
      * |id |code |entity|date      |column1|column2|column3|
      * +---+-----+------+----------+-------+-------+-------+
      * |20 |score|school|2018-03-31|14     |12     |20     |
      * |21 |score|school|2018-03-31|13     |13     |21     |
      * |22 |rate |school|2018-03-31|11     |14     |22     |
      * |21 |rate |school|2018-03-31|13     |12     |23     |
      * +---+-----+------+----------+-------+-------+-------+
      */
    // list of columns
    val cols = Seq("column1", "column2" ,"column3", "column4")
    val processColumns = cols.filter(df.columns.contains).map(sqrt)
    df.select(processColumns: _*).show(false)

    /**
      * +------------------+------------------+-----------------+
      * |SQRT(column1)     |SQRT(column2)     |SQRT(column3)    |
      * +------------------+------------------+-----------------+
      * |3.7416573867739413|3.4641016151377544|4.47213595499958 |
      * |3.605551275463989 |3.605551275463989 |4.58257569495584 |
      * |3.3166247903554   |3.7416573867739413|4.69041575982343 |
      * |3.605551275463989 |3.4641016151377544|4.795831523312719|
      * +------------------+------------------+-----------------+
      */

【讨论】:

  • 感谢您的及时回答我再次更新问题...最后一段..您可以看看它吗?
  • 它有一些有用的东西 thetopsites.net/article/58775028.shtml 但它在 Scala 中。
  • 当我喜欢下面的 df.withColumn("score_org", when( df.schema().fieldNames().contains(col("score")) , col("score")) ) ) 出现错误“无法在数组类型 String[] 上调用 contains(Column)
  • 这里转述的问题你能在同一个stackoverflow.com/questions/63450135/…上给我建议
【解决方案2】:

不确定我是否完全理解您的要求,但您是否只是尝试执行一些条件操作,具体取决于数据框中的哪些列在执行之前不知道?

如果是这样,Dataframe.columns 会返回一个列列表,您可以对其进行解析并相应地选择

df.columns.foreach { println }

【讨论】:

  • 感谢克里斯,但这对我帮助不大。你能检查“数据库中的样本数据”吗?一节。
  • 这里转述的问题你能在同一个stackoverflow.com/questions/63450135/…上给我建议
猜你喜欢
  • 2020-12-06
  • 2019-09-16
  • 2021-02-18
  • 2013-01-10
  • 2020-11-27
  • 2017-04-21
  • 2018-06-24
  • 1970-01-01
  • 2023-03-19
相关资源
最近更新 更多