【问题标题】:Drop column(s) in spark csv data frame删除列)在 spark csv 数据框中
【发布时间】:2017-10-07 09:22:02
【问题描述】:

我有一个数据框,我将其连接到它的所有字段。

连接后它成为另一个数据帧,最后我将其输出写入 csv 文件,并在其两列上进行了分区。它的一列存在于第一个数据帧中,我不想将其包含在最终输出中。

这是我的代码:

val dfMainOutput = df1resultFinal.join(latestForEachKey, Seq("LineItem_organizationId", "LineItem_lineItemId"), "outer")
      .select($"LineItem_organizationId", $"LineItem_lineItemId",
       when($"DataPartition_1".isNotNull, $"DataPartition_1").otherwise($"DataPartition".cast(DataTypes.StringType)).as("DataPartition"),
       when($"StatementTypeCode_1".isNotNull, $"StatementTypeCode_1").otherwise($"StatementTypeCode").as("StatementTypeCode"),
       when($"FFAction_1".isNotNull, concat(col("FFAction_1"), lit("|!|"))).otherwise(concat(col("FFAction"), lit("|!|"))).as("FFAction"))
       .filter(!$"FFAction".contains("D"))

我在这里连接并创建另一个数据框:

val dfMainOutputFinal = dfMainOutput.select($"DataPartition", $"StatementTypeCode",concat_ws("|^|", dfMainOutput.schema.fieldNames.map(c => col(c)): _*).as("concatenated"))     

这是我尝试过的

dfMainOutputFinal
  .drop("DataPartition")
  .write
  .partitionBy("DataPartition","StatementTypeCode")
  .format("csv")
  .option("header","true")
  .option("encoding", "\ufeff")
  .option("codec", "gzip")
  .save("path to csv")

现在我不想在我的输出中出现 DataPartition 列。

我正在基于 DataPartition 进行分区,所以我没有得到,但因为 DataPartition 存在于主数据框中,所以我在输出中得到它。

问题 1:如何忽略 Dataframe 中的列

问题2:有没有办法在写入我的实际数据之前在csv输出文件中添加"\ufeff",这样我的编码格式就会变成UTF-8-BOM。

根据建议的答案

这是我尝试过的

 val dfMainOutputFinal = dfMainOutput.select($"DataPartition", $"StatementTypeCode",concat_ws("|^|", dfMainOutput.schema.filter(_ != "DataPartition").fieldNames.map(c => col(c)): _*).as("concatenated"))

但是遇到错误

<console>:238: error: value fieldNames is not a member of Seq[org.apache.spark.sql.types.StructField]
               val dfMainOutputFinal = dfMainOutput.select($"DataPartition", $"StatementTypeCode",concat_ws("|^|", dfMainOutput.schema.filter(_ != "DataPartition").fieldNames.map(c => col(c)): _*).as("concatenated"))

下面是我是否必须在最终输出中删除两列的问题

  val dfMainOutputFinal = dfMainOutput.select($"DataPartition","PartitionYear",concat_ws("|^|", dfMainOutput.schema.fieldNames.filter(_ != "DataPartition","PartitionYear").map(c => col(c)): _*).as("concatenated"))

【问题讨论】:

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


    【解决方案1】:

    问题一:

    您在df.write.partitionBy() 中使用的列将不会添加到最终的 csv 文件中。由于数据是在文件结构中编码的,因此它们会被自动忽略。但是,如果您的意思是将其从 concat_ws 中删除(从而从文件中删除),则可以进行一些小的更改:

    concat_ws("|^|", 
      dfMainOutput.schema.fieldNames
        .filter(_ != "DataPartition")
        .map(c => col(c)): _*).as("concatenated"))
    

    这里 DataPartition 列在连接之前被过滤掉了。

    问题 2:

    Spark 似乎不支持UTF-8 BOM,并且在读入该格式的文件时似乎会导致problems。除了编写脚本在 Spark 完成后添加它们之外,我想不出任何简单的方法来将 BOM 字节添加到每个 csv 文件中。我的建议是简单地使用普通的UTF-8 格式。

    dfMainOutputFinal.write.partitionBy("DataPartition","StatementTypeCode")
      .format("csv")
      .option("header", "true")
      .option("encoding", "UTF-8")
      .option("codec", "gzip")
      .save("path to csv")
    

    另外,根据Unicode standard,不推荐BOM。

    ... UTF-8 既不需要也不建议使用 BOM,但在 UTF-8 数据从使用 BOM 的其他编码形式转换或 BOM 用作 UTF 的情况下可能会遇到-8 签名。

    【讨论】:

      【解决方案2】:

      问题 1:如何忽略 Dataframe 中的列

      回答:

      val df = sc.parallelize(List(Person(1,2,3), Person(4,5,6))).toDF("age", "height", "weight")
      
      df.columns
      df.show()
      
      
      
      +---+------+------+
      |age|height|weight|
      +---+------+------+
      |  1|     2|     3|
      |  4|     5|     6|
      +---+------+------+
      
      
      val df_new=df.select("age", "height")
          df_new.columns
          df_new.show()
      
      +---+------+
      |age|height|
      +---+------+
      |  1|     2|
      |  4|     5|
      +---+------+
      
      df: org.apache.spark.sql.DataFrame = [age: int, height: int ... 1 more field]
      df_new: org.apache.spark.sql.DataFrame = [age: int, height: int]
      

      问题 2:有没有办法在 csv 输出文件中添加“\ufeff” 在写入我的实际数据之前,我的编码格式将变为 UTF-8-BOM。

      回答:

       String path= "/data/vaquarkhan/input/unicode.csv";
      
       String outputPath = "file:/data/vaquarkhan/output/output.csv";
          getSparkSession()
            .read()
            .option("inferSchema", "true")
            .option("header", "true")
            .option("encoding", "UTF-8")
            .csv(path)
            .write()
            .mode(SaveMode.Overwrite)
            .csv(outputPath);
      }
      

      【讨论】:

      • 我只是不想选择列,我想根据第一个数据帧进行分区,第二个数据帧是从中派生出来的
      猜你喜欢
      • 1970-01-01
      • 2018-03-28
      • 2023-03-28
      • 2023-04-07
      • 2016-10-01
      • 2019-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多