我正在Pyspark中读取csv文件,如下所示:
df_raw=spark.read.option("header","true").csv(csv_path)
但是,数据文件引用了带有嵌入式逗号的字段 不应该被视为逗号。我如何在Pyspark处理这个问题?我知道熊猫可以解决这个问题,但是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
答案 0 :(得分:24)
我注意到你的有问题的行已经转义,它本身使用双引号:
“32 XIY”“W”“JK,RE LK”
应该是解释器
32 XIY“W”JK,RE LK
如RFC-4180第2页中所述 -
这就是Excel所做的事情,例如,默认情况下。
虽然在Spark中(从Spark 2.1开始),默认情况下,使用backslah(\)通过非RFC方式进行转义。要解决此问题,您必须明确告诉Spark使用doublequote作为转义字符使用:
.option('quote', '"')
.option('escape', '"')
这可以解释为逗号字符未被解释为在引用列中。
在Spark Spark网站上没有很好地记录Spark csv格式的选项,但这里有一些较旧的文档,我仍然常常觉得它很有用:
https://github.com/databricks/spark-csv
2018年8月更新:Spark 3.0可能会将此行为更改为RFC投诉。有关详细信息,请参阅SPARK-22236。
答案 1 :(得分:16)
对于在Scala中这样做的人:Tagar的答案几乎对我有用(谢谢!);在设置我的选项参数时,我所要做的就是逃避双引号:
.option("quote", "\"")
.option("escape", "\"")
我正在使用Spark 2.3,因此我可以确认Tagar的解决方案在新版本下似乎仍然有效。
答案 2 :(得分:2)
默认情况下,comma
内指定的分隔符(quotes
)将被忽略。 Spark SQL在Spark 2.0中有内置的CSV阅读器。
df = session.read
.option("header", "true")
.csv("csv/file/path")