删除spark csv数据框中的列

时间:2017-10-07 09:22:03

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

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

连接后,它变成另一个数据帧,最后我将其输出写入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"))

2 个答案:

答案 0 :(得分:1)

问题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,但在使用BOM的其他编码形式或将BOM用作UTF的UTF-8数据转换的上下文中可能会遇到-8签名。

答案 1 :(得分:0)

  

问题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:有没有办法添加&#34; \ ufeff&#34;在csv输出文件中   在编写我的实际数据之前,我的编码格式将变为   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);
}