【问题标题】:Replace Special characters of column names in Spark dataframe替换 Spark 数据框中列名的特殊字符
【发布时间】:2020-12-29 01:16:25
【问题描述】:

我的输入 spark-dataframe 命名为 df

+---------------+----------------+-----------------------+
|Main_CustomerID|126+ Concentrate|2.5 Ethylhexyl_Acrylate|
+---------------+----------------+-----------------------+
|         725153|             3.0|                    2.0|
|         873008|             4.0|                    1.0|
|         625109|             1.0|                    0.0|
+---------------+----------------+-----------------------+

我需要从df 的列名中删除特殊字符,如下所示,

  • 删除+

  • 将空格替换为underscore

  • dot 替换为underscore

所以我的df 应该是这样的

+---------------+---------------+-----------------------+
|Main_CustomerID|126_Concentrate|2_5_Ethylhexyl_Acrylate|
+---------------+---------------+-----------------------+
|         725153|            3.0|                    2.0|
|         873008|            4.0|                    1.0|
|         625109|            1.0|                    0.0|
+---------------+---------------+-----------------------+

使用 Scala,我实现了这一点,

var tableWithColumnsRenamed = df

for (field <- tableWithColumnsRenamed.columns) {
      tableWithColumnsRenamed = tableWithColumnsRenamed
        .withColumnRenamed(field, field.replaceAll("\\.", "_"))
    }
for (field <- tableWithColumnsRenamed.columns) {
      tableWithColumnsRenamed = tableWithColumnsRenamed
        .withColumnRenamed(field, field.replaceAll("\\+", ""))
    }
for (field <- tableWithColumnsRenamed.columns) {
      tableWithColumnsRenamed = tableWithColumnsRenamed
        .withColumnRenamed(field, field.replaceAll(" ", "_"))
    }

df = tableWithColumnsRenamed

当我使用时,

for (field <- tableWithColumnsRenamed.columns) {
      tableWithColumnsRenamed = tableWithColumnsRenamed
        .withColumnRenamed(field, field.replaceAll("\\.", "_"))
    .withColumnRenamed(field, field.replaceAll("\\+", ""))
    .withColumnRenamed(field, field.replaceAll(" ", "_"))
    }

我得到的第一列名称是126 Concentrate,而不是126_Concentrate

但我不喜欢用 3 个 for 循环来替换。我能得到解决方案吗?

【问题讨论】:

    标签: scala replace apache-spark-sql


    【解决方案1】:
    df
      .columns
      .foldLeft(df){(newdf, colname) =>
        newdf.withColumnRenamed(colname, colname.replace(" ", "_").replace(".", "_"))
      }
      .show
    

    【讨论】:

    • 是的,它运行良好。根据我的用例,我将解决方案更改为df.columns.foldLeft(df){(newdf, colname) =&gt; newdf.withColumnRenamed(colname,colname.replace(" ", "_").replace(".", "_").replace("+",""))}
    【解决方案2】:

    你可以使用withColumnRenamedregex replaceAllInfoldLeft如下

    val columns = df.columns
    
    val regex = """[+._, ]+"""
    val replacingColumns = columns.map(regex.r.replaceAllIn(_, "_"))
    
    val resultDF = replacingColumns.zip(columns).foldLeft(df){(tempdf, name) => tempdf.withColumnRenamed(name._2, name._1)}
    
    resultDF.show(false)
    

    这应该给你

    +---------------+---------------+-----------------------+
    |Main_CustomerID|126_Concentrate|2_5_Ethylhexyl_Acrylate|
    +---------------+---------------+-----------------------+
    |725153         |3.0            |2.0                    |
    |873008         |4.0            |1.0                    |
    |625109         |1.0            |0.0                    |
    +---------------+---------------+-----------------------+
    

    希望回答对你有帮助

    【讨论】:

      【解决方案3】:

      在 java 中,您可以使用 df.columns() 遍历列名并将每个标题字符串替换为 string replaceAll(regexPattern, IntendedCharreplacement)

      然后使用withColumnRenamed(headerName, correctedHeaderName) 重命名df 标头。

      例如-

      for (String headerName : dataset.columns()) {
          String correctedHeaderName = headerName.replaceAll(" ","_").replaceAll("+","_");
          dataset = dataset.withColumnRenamed(headerName, correctedHeaderName);
      }
      dataset.show();
      

      【讨论】:

        【解决方案4】:

        捎带 Ramesh 的答案,这是一个可重用的函数,它使用带有 .transform() 方法的柯里化语法 & 使列小写:

        // Format all column names with regex with lower_case names
        def formatAllColumns(regex_string:String)(df: DataFrame): DataFrame = {
          val replacingColumns = df.columns.map(regex_string.r.replaceAllIn(_, "_"))
          val resultDF:DataFrame = replacingColumns.zip(df.columns).foldLeft(df){
            (tempdf, name) => tempdf.withColumnRenamed(name._2, name._1.toLowerCase())
          }
          resultDF
        }
        val resultDF = df.transform(formatAllColumns(regex_string="""[+._(), ]+"""))
        

        【讨论】:

          【解决方案5】:

          我们可以通过在使用 replaceAll 替换特殊字符后将 column_name 映射为新名称来删除所有字符,并使用 spark scala 尝试和测试这一单行代码。

          df.select(
                    df.columns
                      .map(colName => col(s"`${colName}`").as(colName.replaceAll("\\.", "_").replaceAll(" ", "_"))): _*
                  ).show(false)
          

          【讨论】:

          • 虽然这段代码可以解决问题,但如果解释一下它的作用方式/原因,答案会好得多。请记住,您的答案不仅适用于提出问题的用户,还适用于所有其他找到该问题的人。
          猜你喜欢
          • 2014-05-04
          • 2019-02-19
          • 2020-12-15
          • 1970-01-01
          • 2022-07-01
          • 2022-09-23
          • 2016-08-30
          • 2018-11-23
          • 2017-05-26
          相关资源
          最近更新 更多