Je lis un fichier csv dans Pyspark comme suit:
df_raw=spark.read.option("header","true").csv(csv_path)
Cependant, le fichier de données contient des champs avec des virgules incorporées qui ne doivent pas être traités comme des virgules. Comment puis-je gérer cela dans Pyspark? Je sais pandas peut gérer cela, mais peut Spark? La version que j'utilise est Spark 2.0.0.
Voici un exemple qui fonctionne en Pandas mais échoue en utilisant 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|
+------------------+--------------------+--------------------+
Le contenu du fichier:
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
J'ai remarqué que votre ligne problématique s'est échappée et utilise des guillemets:
"32 XIY" "W" "JK, RE LK"
qui devrait être interprète tout comme
32 XIY "W" JK, RE LK
Comme décrit dans RFC-418 , page 2 -
C'est ce que fait Excel, par exemple, par défaut.
Bien que dans Spark (à partir de Spark 2.1), l'échappement est effectué par défaut de manière non RFC, en utilisant backslah (\). Pour résoudre ce problème, vous devez pour dire explicitement Spark pour utiliser la double guillemet à utiliser comme caractère d'échappement:
.option('quote', '"')
.option('escape', '"')
Cela peut expliquer qu'un caractère virgule n'a pas été interprété comme il était à l'intérieur d'une colonne entre guillemets.
Les options pour le format Spark csv ne sont pas bien documentées sur le site Apache Spark, mais voici une documentation un peu plus ancienne que je trouve toujours utile assez souvent:
https://github.com/databricks/spark-csv
Mise à jour d'août 2018 : Spark 3.0 peut changer ce comportement pour être conforme aux RFC. Voir SPARK- 22236 pour plus de détails.
Pour tous ceux qui font cela dans Scala: la réponse de Tagar a presque fonctionné pour moi (merci!); tout ce que j'avais à faire était d'échapper à la double citation lors du paramétrage de mon option:
.option("quote", "\"")
.option("escape", "\"")
J'utilise Spark 2.3, donc je peux confirmer que la solution de Tagar semble toujours fonctionner de la même manière dans la nouvelle version.
Le délimiteur (comma
) spécifié dans quotes
sera ignoré par défaut. Spark SQL a un lecteur CSV intégré dans Spark 2.0.
df = session.read
.option("header", "true")
.csv("csv/file/path")