Чтение csv файлов с цитируемыми полями, содержащими встроенные запятые

Я читаю файл csv в Pyspark следующим образом:

df_raw=spark.read.option("header","true").csv(csv_path)

Однако в файле данных указаны поля со встроенными запятыми, в которых не следует рассматривать как запятые. Как я могу справиться с этим в Pyspark? Я знаю, что pandas может справиться с этим, но может ли Spark? Версия, которую я использую, - Spark 2.0.0.

Вот пример, который работает в pandas, но не работает с помощью Spark:

In [1]: import pandas as pd

In [2]: pdf = pd.read_csv('malformed_data.csv')

In [3]: sdf=spark.read.format("org.apache.spark.csv").csv('malformed_data.csv',header=True)

In [4]: pdf[['col12','col13','col14']]
Out[4]:
                    col12                                             col13  \
0  32 XIY "W"   JK, RE LK  SOMETHINGLIKEAPHENOMENON#YOUGOTSOUL~BRINGDANOISE
1                     NaN                     OUTKAST#THROOTS~WUTANG#RUNDMC

   col14
0   23.0
1    0.0

In [5]: sdf.select("col12","col13",'col14').show()
+------------------+--------------------+--------------------+
|             col12|               col13|               col14|
+------------------+--------------------+--------------------+
|"32 XIY ""W""   JK|              RE LK"|SOMETHINGLIKEAPHE...|
|              null|OUTKAST#THROOTS~W...|                 0.0|
+------------------+--------------------+--------------------+

Содержимое файла:

    col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12,col13,col14,col15,col16,col17,col18,col19
80015360210876000,11.22,X,4076710258,,,sxsw,,"32 YIU ""A""",S5,,"32 XIY ""W""   JK, RE LK",SOMETHINGLIKEAPHENOMENON#YOUGOTSOUL~BRINGDANOISE,23.0,cyclingstats,2012-25-19,432,2023-05-17,CODERED
61670000229561918,137.12,U,8234971771,,,woodstock,,,T4,,,OUTKAST#THROOTS~WUTANG#RUNDMC,0.0,runstats,2013-21-22,1333,2019-11-23,CODEBLUE

Ответ 1

Я заметил, что у вашей проблемной строки есть экранирование, в котором используются двойные кавычки:

"32 XIY" "W" "JK, RE LK"

который должен быть переводчиком так же, как

32 XIY "W" JK, RE LK

Как описано в RFC-4180, стр. 2 -

  1. Если двойные кавычки используются для включения полей, то двойная кавычка, появляющаяся внутри поля, должна быть экранирована, предшествуя другой двойной кавычке

То, что делает Excel, например, по умолчанию.

Хотя в Spark (по состоянию на Spark 2.1) экранирование выполняется по умолчанию не по RFC, используя обратную косую черту (\). Чтобы это исправить, вы должны явно указать Spark использовать двойную кавычку для использования в качестве escape-символа:

.option('quote', '"')
.option('escape', '"')

Это может объяснить, что символ запятой не интерпретировался так, как внутри столбца в кавычках.

Опции для формата Spark csv плохо документированы на сайте Apache Spark, но здесь есть немного более старая документация, которую я все еще нахожу полезной довольно часто:

https://github.com/databricks/spark-csv

Обновление Авг 2018: Spark 3.0 может изменить это поведение, чтобы быть RFC-совместимым. См. SPARK-22236 для деталей.

Ответ 2

Для тех, кто делает это в Scala: ответ Тагара почти сработал у меня (спасибо!); все, что мне нужно было сделать, это избежать двойной кавычки при настройке моего параметра param:

.option("quote", "\"")
.option("escape", "\"")

Я использую Spark 2.3, поэтому я могу подтвердить, что решение Tagar по-прежнему работает так же в новой версии.

Ответ 3

Разделитель (comma), указанный внутри quotes будет игнорироваться по умолчанию. Spark SQL имеет встроенный CSV-ридер в Spark 2.0.

df = session.read
  .option("header", "true")
  .csv("csv/file/path")

больше о читателе CSV здесь -.