代码之家  ›  专栏  ›  技术社区  ›  samba

scala-如何在最后一个点后对子串列名?

  •  0
  • samba  · 技术社区  · 6 年前

    分解嵌套结构后,我有一个数据帧,其列名如下:

    sales_data.metric1
    sales_data.type.metric2
    sales_data.type3.metric3
    

    执行选择操作时,出现错误:

    cannot resolve 'sales_data.metric1' given input columns: [sales_data.metric1, sales_data.type.metric2, sales_data.type3.metric3]
    

    我应该如何从数据框中选择,以便正确分析列名?

    我尝试过以下方法:成功提取点后的子串。但是因为我也有没有点的列 date -他们的名字被完全删除了。

    var salesDf_new = salesDf 
    for(col <- salesDf .columns){
      salesDf_new = salesDf_new.withColumnRenamed(col, StringUtils.substringAfterLast(col, "."))
    }
    

    我只想离开metric1,metric2,metric3

    1 回复  |  直到 6 年前
        1
  •  1
  •   Ryan Widmaier    6 年前

    可以使用反勾号选择名称中包含句点的列。

    val df = (1 to 1000).toDF("column.a.b")
    
    df.printSchema
    // root
    //  |-- column.a.b: integer (nullable = false)
    
    df.select("`column.a.b`")
    

    另外,您可以像这样轻松地重命名它们。基本上从当前数据帧开始,用每个字段的新列名不断更新它,并返回最终结果。

    val df2 = df.columns.foldLeft(df)(
        (myDF, col) => myDF.withColumnRenamed(col, col.replace(".", "_"))
    )
    

    编辑:获取最后一个组件

    要仅使用姓氏组件重命名,此正则表达式将工作:

    val df2 = df.columns.foldLeft(df)(
        (myDF, col) => myDF.withColumnRenamed(col, col.replaceAll(".+\\.([^.]+)$", "$1"))
    )
    

    编辑2:获取最后两个组件

    这有点复杂,可能有一种更干净的方法来写,但这里有一种方法可以工作:

    val pattern = (
        ".*?"  +          // Lazy match leading chars so we ignore that bits we don't want
        "([^.]+\\.)?" +   // Optional 2nd to last group
        "([^.]+)$"        // Last group
    )
    
    val df2 = df.columns.foldLeft(df)(
        (myDF, col) => myDF.withColumnRenamed(col, col.replaceAll(pattern, "$1$2"))
    )
    df2.printSchema