我需要在Pandas中读取CSV文件,该文件的数据格式如下(其中一个字段用双“双引号”表示)
"column1","column2","column3","column4"
"10",""AB"","ABCD","abcd"
"11",""CD,E"","CDEF","abcd"
"12",""WER"","DEF,31","abcd"
我希望正确解析的数据帧像
column1 column2 column3 column4
10 AB ABCD abcd
11 "CD,E" CDEF abcd
12 WER "DEF,31" abcd
我尝试使用
df= pd.read_csv('sample.txt',quotechar='""', quoting=csv.QUOTE_ALL)
和
df= pd.read_csv('sample.txt',quotechar='"', quoting=csv.QUOTE_ALL)
但是得到
TypeError: "quotechar" must be a 1-character string
和
pandas.errors.ParserError: Error tokenizing data. C error: Expected 4 fields in line 3, saw 5
有没有一种方法可以让我按原样读取此文件,而无需预处理并删除数据中的双“双引号”?
当column2
没有逗号时,我可以读取带有一些额外引号的数据,这些引号可以在以后的处理步骤中替换。仅当column2
带有逗号时,我才遇到解析问题。
答案 0 :(得分:1)
我不确定熊猫是否可以单独执行此操作,因为您的数据中同时包含未转义的分隔符和引号。
但是,在使用正则表达式修改数据后,您应该能够通过转义字段中的引号将其解析。
import re
from io import StringIO
data = """
"column1","column2","column3","column4"
"10",""AB"","ABCD","abcd"
"11",""CD,E"","CDEF","abcd"
"12",""WER"","DEF,31","abcd"
"""
data = re.sub('(?<!^)"(?!,")(?<!,")(?!$)', '\\"', data, flags=re.M)
pd.read_csv(StringIO(data), escapechar='\\')
如果您正在读取文件,则:
with open('path/to/csv', 'r') as f:
data = re.sub('(?<!^)"(?!,")(?<!,")(?!$)', '\\"', f.read(), flags=re.M)
df = pd.read_csv(StringIO(data), escapechar='\\')
正则表达式将查找不在每行开头(?<!^)
或结尾(?!$)
处的引号,并查找不在开头(?<!,")
和结尾{{1中的引号}}的每个字段
答案 1 :(得分:1)
这应该为您解决问题
df =pd.read_csv("so.txt",encoding='utf-8', names=["column1","column2","column3","column4"],sep='",',header=0,quoting=csv.QUOTE_ALL)
答案 2 :(得分:0)
预处理不一定是坏事。如果使用系统管道完成,则不会增加太多开销(如上面带有 StringIO
的开销)。它还可以节省大量时间来解决一些已知问题(例如 DOS CR、EOF 处没有 EOL、中间有 NULL 字节等,具体取决于您的系统)。
对于这种情况+一些其他常见问题,例如额外的引号、空格、逗号、嵌入的逗号。虽然 pandas
确实有一个参数 doublequote
,但它不够灵活。
使用系统管道,对于 Linux 上的大文件应该很有效
import os
df = pd.read_csv(
os.popen('sed -r "s/^\s+|(^[,[:space:]]*|\s*)(#.*)?$//g; s/\s+,/,/g; s/\\"\\"/\\"/g" %s' % fname),
quotechar='"', skipinitialspace=True)
或:使用 python 管道
import re
from io import StringIO
with open(fname) as f:
data = re.sub('""', '"', re.sub('[ \t]+,', ',',
re.sub('^[ \t]+|(^[ \t,]*|[ \t]*)(#.*)?$', '', f.read(), flags=re.M)))
df = pd.read_csv(StringIO(data), quotechar='"', skipinitialspace=True)
带有评论和问题的输入文件
a, b, c, d # header w/ trailing spaces
,, ,,,, # commas + spaces, no data
# extra space before data
1, 2, 3.5, 4k
3, " 5 " , 7.6, "n, m" # extra spaces, comma inside
10, "20" , 30.5, w z
40, 60, 75, ""x, q"" # double quoting
输出:
a b c d
0 1 2 3.5 4k
1 3 5 7.6 n, m
2 10 20 30.5 w z
3 40 60 75.0 x, q
现在干净且格式正确:
a int64
b int64
c float64
d object
list(df['d']): ['4k', 'n, m', 'w z', 'x, q']