如何修复火花可怕地误解 csv?

Posted

技术标签:

【中文标题】如何修复火花可怕地误解 csv?【英文标题】:How to fix spark horribly misinterpreting csv? 【发布时间】:2017-12-15 20:23:10 【问题描述】:

我有两个 csv 文件,一个包含电影的关键字,另一个包含演员和工作人员。 keywords.csv 文件如下所示:

$ head -n 3 keywords.csv
id,keywords
862,"['id': 931, 'name': 'jealousy', 'id': 4290, 'name': 'toy', 'id': 5202, 'name': 'boy', 'id': 6054, 'name': 'friendship', 'id': 9713, 'name': 'friends', 'id': 9823, 'name': 'rivalry', 'id': 165503, 'name': 'boy next door', 'id': 170722, 'name': 'new toy', 'id': 187065, 'name': 'toy comes to life']"
8844,"['id': 10090, 'name': 'board game', 'id': 10941, 'name': 'disappearance', 'id': 15101, 'name': ""based on children's book"", 'id': 33467, 'name': 'new home', 'id': 158086, 'name': 'recluse', 'id': 158091, 'name': 'giant insect']"

credits.csv 文件如下所示:

$ head -n 2 credits.csv
cast,crew,id
"['cast_id': 14, 'character': 'Woody (voice)', 'credit_id': '52fe4284c3a36847f8024f95', 'gender': 2, 'id': 31, 'name': 'Tom Hanks', 'order': 0, 'profile_path': '/pQFoyx7rp09CJTAb932F2g8Nlho.jpg', 'cast_id': 15, 'character': 'Buzz Lightyear (voice)', 'credit_id': '52fe4284c3a36847f8024f99', 'gender': 2, 'id': 12898, 'name': 'Tim Allen', 'order': 1, 'profile_path': '/uX2xVf6pMmPepxnvFWyBtjexzgY.jpg']", 1

两者都是格式正确的 csv,pandas 读入没有问题。Spark 像这样读入它们:

spark.read
  .option("quote", "\"")
  .option("delimiter", ",")
  .option("header", "true")
  .csv("keywords.csv")
  .show(2)

输出:

+-------+--------------------+
|movieId|            keywords|
+-------+--------------------+
|    862|['id': 931, 'nam...|
|   8844|"['id': 10090, '...|
+-------+--------------------+

它清楚地显示了第一行和第二行之间的差异(注意 " 字符的存在/不存在。这可以通过包含字符串替换的简单 udf 来解决。

对于credits.csv,它出现了可怕的错误:

spark.read
  .option("quote", "\"")
  .option("delimiter", ",")
  .option("header", "true")
  .csv("credits.csv")
  .show(2)

输出:

+--------------------+--------------------+--------------------+
|                cast|                crew|             movieId|
+--------------------+--------------------+--------------------+
|['cast_id': 14, ...|"['credit_id': '...| 'profile_path': ...|
|['cast_id': 1, '...|['credit_id': '5...|                8844|
+--------------------+--------------------+--------------------+

列已损坏...

如何在不破坏列的情况下正确(如果可能)阅读此内容?我很惊讶pandas 没有问题,而 spark 却惨遭失败。

【问题讨论】:

您的credits.csv 样本,假设我从表面上看引号字符,只有两个字段。第一个字段字符串看起来像一个包含两个字典的列表;第二个字段是一个整数。 【参考方案1】:

对于第一个文件,您使用了错误的转义字符 - csv 中的默认值是 \,而您的文件使用了 "

>>> (spark.read
...   .option("escape", '"')
...   .option("header", "true")
...   .csv("keywords.csv")
...   .show(2))
...   
+----+--------------------+
|  id|            keywords|
+----+--------------------+
| 862|['id': 931, 'nam...|
|8844|['id': 10090, 'n...|
+----+--------------------+

在第二个文件(credits.csv)中也有同样的问题,另外头部中的字段数与数据不匹配(comment by Kirk Broadhurst)它无法在 Spark 中正确加载:

>>> (spark.read
...   .option("escape", '"')
...   .option("header", "true")
...   .csv("credits.csv")
...   .show(2))
...   
+--------------------+----+----+
|                cast|crew|  id|
+--------------------+----+----+
|['cast_id': 14, ...|   1|null|
+--------------------+----+----+

和熊猫一样:

>>> pd.read_csv("credits.csv")
                                                cast  crew  id
0  ['cast_id': 14, 'character': 'Woody (voice)',...     1 NaN

【讨论】:

以上是关于如何修复火花可怕地误解 csv?的主要内容,如果未能解决你的问题,请参考以下文章

细数人们对安卓的误解

动态负载库和运行时误解的显式链接

这是 Files.lines() 中的错误,还是我对并行流有误解?

关于Java常见的误解

对私有云的误解有这三点

学习记录:软件测试的最常见的误解