【问题标题】:How to clean a CSV file for reading text in double quotes as one column如何清理 CSV 文件以将双引号中的文本作为一列读取
【发布时间】:2018-01-05 01:09:07
【问题描述】:

我正在使用 Scala 和 Apache Spark 处理包含芝加哥犯罪数据的数据集

有几行中多个值用逗号分隔并放在双引号中。有没有办法清理数据,以便双引号下的文本可以作为一列读取

文本在下面,粗体的列是我想作为单列阅读的内容

10366565,HZ102660,01/03/2016 01:50:00 PM,020XX S WABASH AVE,1310,CRIMINAL DAMAGE,TO PROPERTY,**“SCHOOL, PRIVATE, BUILDING”**,false,false,0131,001,3,33,14,1177070,1890608,2016,01/10/2016 08:46:55 AM,41.855167994,-87.625552607,"(41.855167994, -87.625552607)"

所需的输出如下所示,以便可以通过删除逗号将引号下的文本作为单个字符串读取:

10366565,HZ102660,01/03/2016 01:50:00 PM,020XX S WABASH AVE,1310,CRIMINAL DAMAGE,TO PROPERTY,**“SCHOOL|PRIVATE|BUILDING”**,false,false,0131,001,3,33,14,1177070,1890608,2016,01/10/2016 08:46:55 AM,41.855167994,-87.625552607,**"(41.855167994|-87.625552607)"**

有没有办法在 Scala 中执行此操作或使用 shell 脚本将其转换为新文件?

【问题讨论】:

  • 请将该示例输入的所需输出添加到您的问题中。
  • @Cyrus 完成了编辑
  • sed 's/, /|/g' file?
  • 以后,请在每行代码/数据/错误消息的前面使用4个空格或突出显示一个文本块并使用编辑左上角的{}格式工具框格式化为代码/数据/输出。有关详细信息,请参阅 editing-helpformatting。很高兴您有一个快速的解决方案。祝你好运。

标签: bash scala csv apache-spark


【解决方案1】:

默认情况下,Spark 将 CSV 文件中的带引号的字符串(无论是否包含逗号)作为单列,因此如果您愿意,可以在将带引号的内容读入 DataFrame 后对其进行处理:

CSV 数据示例:

10366565,01/03/2016 01:50:00 PM,"SCHOOL, PRIVATE, BUILDING"
10366700,01/04/2016 12:30:00 PM,"SCHOOL, PRIVATE, BUILDING"

示例代码:

val df = spark.read.csv("/path/to/csvfile")

+--------+----------------------+-------------------------+
|_c0     |_c1                   |_c2                      |
+--------+----------------------+-------------------------+
|10366565|01/03/2016 01:50:00 PM|SCHOOL, PRIVATE, BUILDING|
|10366700|01/04/2016 12:30:00 PM|SCHOOL, PRIVATE, BUILDING|
+--------+----------------------+-------------------------+

// A UDF function that converts ",\s*" to "|"
def commaToPipe = udf( (s: String) =>
  """,\s*""".r.replaceAllIn(s, "|")
)

df.select($"_c0", commaToPipe($"_c2")).show(truncate=false)
+--------+-----------------------+
|_c0     |UDF(_c2)               |
+--------+-----------------------+
|10366565|SCHOOL|PRIVATE|BUILDING|
|10366700|SCHOOL|PRIVATE|BUILDING|
+--------+-----------------------+

[更新]

正如评论者指出的那样,使用 regexp_replace 将消除对 UDF 的需求:

df.select($"_c0", regexp_replace($"_c2", """,\s*""", "|"))

【讨论】:

  • regexp_replace 可以代替 UDF 正常工作。
  • 感谢@philantrovert,Spark 的原生功能当然是首选。答案已更新。
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 2019-05-02
  • 2012-01-12
  • 2014-10-28
  • 2020-09-18
  • 2022-01-16
  • 2019-06-28
  • 2019-10-31
相关资源
最近更新 更多