起因
用pandas.read_csv读取csv文件,结果在读到下面两行的时候总是报错说列数过多:
124832,"Zehut Sh'ula\"",,7,1997,,Z324,124831,1,3,,3ecbb0386bee44d925ff0fcdb11e11b8
80501,"Co-Host Andy Cohen; \"Steel Magnolias\" Cast: Queen Latifah, Alfre Woodard, Jill Scott",,7,2012,,C2353,80464,2,26,,4ec914112555c0fb2180cc7cab41c67
ps:这两行并不相邻
但是肉眼看过去,这两列的数据并没有什么问题,盲猜是引号导致的问题,因为其他地方都很正常,简单尝试删去某个引号后跑通了,但是不理解原因,而且按理说不应该改动数据,于是开始搜索相关问题。
分析
step1
在stackoverflow上看到这样一则问答https://stackoverflow.com/questions/23934613/reading-a-csv-file-to-pandas-error-expected-after,不过这个是引号嵌套使用导致的,和我的情况不太符合,不过让我更加确信是pandas.read_csv在处理引号的时候出了问题。
于是我干脆把上面出问题的两列单拿出来看看pandas到底是怎么读的,创建csv如下:
c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14
124832,"Zehut Sh'ula\"",,7,1997,,Z324,124831,1,3,,3ecbb0386bee44d925ff0fcdb11e11b8
80501,"Co-Host Andy Cohen; \"Steel Magnolias\" Cast: Queen Latifah, Alfre Woodard, Jill Scott",,7,2012,,C2353,80464,2,26,,4ec914112555c0fb2180cc7cab41c671
python代码:
# read csv in this folder named 14or12? with headers
# and show the content of the file
import pandas as pd
df = pd.read_csv('14or12?', sep=',')
# show the content of the file, don't abbreviate
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
print(df)
得到的结果让我大吃一惊,竟然是:
c1 c2 c3 \
0 124832 Zehut Sh'ula\",,7,1997,,Z324,124831,1,3,,3ecbb... Alfre Woodard
c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 \
0 Jill Scott" NaN 7 2012 NaN C2353 80464 2 26 NaN
c14
0 4ec914112555c0fb2180cc7cab41c671
可以看到两行数据变成了一行,c2这列数据明显异常,似乎引号囊括了过多的内容。基本可以猜测是Zehut Sh'ula\"
附近的问题
step2
为了进一步确认问题出在哪儿,以及为什么会产生这样的结果,我在Zehut Sh’ula\"处加了一些字母作为tag:
c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14
124832,"Zehut Sh'ula\"aa",,7,1997,,Z324,124831,1,3,,3ecbb0386bee44d925ff0fcdb11e11b8
80501,"Co-Host Andy Cohen; \"Steel Magnolias\" Cast: Queen Latifah, Alfre Woodard, Jill Scott",,7,2012,,C2353,80464,2,26,,4ec914112555c0fb2180cc7cab41c671
输出为:
c1 c2 c3 \
0 124832 Zehut Sh'ula\aa" NaN
1 80501 Co-Host Andy Cohen; \Steel Magnolias\" Cast: Q... Alfre Woodard
c4 c5 c6 c7 c8 c9 c10 c11 \
0 7 1997.0 NaN Z324 124831.0 1 3 NaN
1 Jill Scott" NaN 7.0 2012 NaN C2353 80464 2.0
c12 c13 c14
0 3ecbb0386bee44d925ff0fcdb11e11b8 NaN NaN
发现结果又变成了两行,似乎正常了一点,但仔细看row0c2处是Zehut Sh'ula\aa"
,说明read_csv把\"
中的"
当成了正常的引号,而不是转义后的引号。至于为什么后面的解析又变得正确了,目前不得而知,按照我的理解,结果应该和step1中类似才对,不知道为什么Zehut Sh'ula\aa"
中最后的引号被当成了普通字符。
但是可以基本确认问题出在转移字符上,于是开始搜索相关问题。
解决
查了很多问答和博客,都没有找到问题的关键,后面找到了一些博客说pandas.read_csv()默认的转义字符是双引号?如果想表示"
,就要用引号扩起来,"""
这样子(未经证实)
想来原理应该并不是转义字符而是把引号内的内容当做普通字符,但是这就存在一个组合问题,也就是为什么不是把前两个
"
当做一组,最后的"
当做不闭合的引号呢?
总之确定了问题就是pandas并没有把\
理解为转义字符,于是去看了文档,加上参数
escapechar='\\'
就好了(加两个是因为\
本身在python里就是转义字符,需要用\\
来表示\
本身)。
最终结果
# read csv in this folder named 14or12? with headers
# and show the content of the file
import pandas as pd
df = pd.read_csv('14or12?', sep=',', escapechar='\\')
# show the content of the file, don't abbreviate
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
print(df)
c1 c2 c3 c4 c5 \
0 124832 Zehut Sh'ula" NaN 7 1997
1 80501 Co-Host Andy Cohen; "Steel Magnolias" Cast: Qu... NaN 7 2012
c6 c7 c8 c9 c10 c11 c12 c13 c14
0 NaN Z324 124831 1 3 NaN 3ecbb0386bee44d925ff0fcdb11e11b8 NaN NaN
1 NaN C2353 80464 2 26 NaN 4ec914112555c0fb2180cc7cab41c671 NaN NaN