使用以下CSV文件:
"aa"!#"2811"!#"Location"!#"11"!#"67000"!#"ZZ"
"bb"!#2812!#"Location"!#"22"!#"67540"!#"XX"
"cc"!#"2813"!#Location!#"33"!#"67117"!#"YY"
"dd"!#"2452"!#"location"!#"44"!#"67000"!#"ZZ"
使用以下python代码:
import pandas
import csv
pandas.read_csv("test.csv", sep="!#", header=None, quotechar='"')
给出以下结果:
0 0 1 2 3 4 5
0 "aa" "2811" "Location" "11" "67000" "ZZ"
1 "bb" 2812 "Location" "22" "67540" "XX"
2 "cc" "2813" Location "33" "67117" "YY"
3 "dd" "2452" "location" "44" "67000" "ZZ"
但是,正如我指定的quotechar='"'
,结果应为
0 1 2 3 4 5
0 aa 2811 Location 11 67000 ZZ
1 bb 2812 Location 22 67540 XX
2 cc 2813 Location 33 67117 YY
3 dd 2452 location 44 67000 ZZ
我错过了什么吗?
修改:按!#
替换所有,
使其正常工作,显然,quotechar
不会被解释为sep
,超过1个字符。所以,我正在寻找一个没有str.replace()
的解决方案(我无法更改!#
,而"
非常重要,因为!#
可以找到一栏。
答案 0 :(得分:3)
请看这里: python pandas read_csv quotechar does not work
如果分隔符是多个字符,则quotechar不起作用。我尝试使用逗号作为分隔符,它可以工作。
答案 1 :(得分:2)
这是一种解决方法:
import re
data = []
with open(filename, 'r') as f:
for row in f:
data.append([re.sub(r'^"|"$', '', item).strip() for item in row.split('!#')])
df = pd.DataFrame(data)
>>> print(df)
0 1 2 3 4 5
0 aa 2811 Location 11 67000 ZZ
1 bb 2812 Location 22 67540 XX
2 cc 2813 Location 33 67117 YY
3 dd 2452 location 44 67000 ZZ
有关正则表达式的解释,它会删除在每个已解析字符串的开头或结尾找到的双引号。
^"
在字符串的开头断言引号的位置。"$
在字符串的末尾断言引号的位置。|
匹配上面的断言。 [re.sub(r'^"|"$', '', item).strip() for item in row.split('!#')]
是一个列表解析,它从行的每个已解析元素中删除起始和结束引用,并删除所有空格。
答案 2 :(得分:0)
df = pd.read_csv("test.csv", delimiter="!#", header=None)
df = df.apply(lambda x: x.str.strip('"'))
输出
0 1 2 3 4 5
0 aa 2811 Location 11 67000 ZZ
1 bb 2812 Location 22 67540 XX
2 cc 2813 Location 33 67117 YY
3 dd 2452 location 44 67000 ZZ
答案 3 :(得分:0)
您也可以在阅读文件后使用替换功能
data = pd.read_csv('/Users/a70286/Desktop/temp.csv',sep="!#", header=None)
data.apply(lambda x: x.str.replace('"',""))
答案 4 :(得分:0)
我们知道使用带有pd.read_csv
的多字符分隔符会调用正则表达式引擎并使用正则表达式分隔符prone to ignoring quoted data - 至少,我看不出它是如何完成的,特别是如果我们希望!#
在一对引号内被视为非分隔符。
因此,如果我们要使用pd.read_csv
,我们将不得不使用单字符分隔符。
它会是什么?如果我们使用sep='!'
,则某些列将以#
开头 - 这将模糊初始引号的含义。清理引号是一件不必要的麻烦(请注意X周围的双引号未正确解析):
In [218]: pd.read_csv(StringIO(content), sep='!', quotechar='"', header=None)
Out[218]:
0 1 2 3 4 5
0 a!#a #"2811" #"Location ""X""" #"11" #"67000" #"1"
1 bb #2812 #"Location" #"22" #"67540" #"2"
2 cc #"2813" #Location #"33" #"67117" #"3"
3 dd #"2452" #"location" #"44" #"67000" #"4"
因此最好使用sep='#'
。所以我们的手基本上是强迫的:我们需要使用sep='#'
和quotechar='"'
:
In [219]: pd.read_csv(StringIO(content), sep='#', quotechar='"', header=None)
Out[219]:
0 1 2 3 4 5
0 a!#a! 2811! Location "X"! 11! 67000! 1
1 bb! 2812! Location! 22! 67540! 2
2 cc! 2813! Location! 33! 67117! 3
3 dd! 2452! location! 44! 67000! 4
但是,我们需要事后清理!
,但至少引用得到适当尊重(请注意!#
内的a!#a!
未被解释作为分隔符)。
下面的代码显示了如何删除!
并将数字字符串转换为数字:
import pandas as pd
StringIO = pd.io.common.StringIO
content = '''\
"a!#a"!#"2811"!#"Location ""X"""!#11!!#"67000"!#"1"
"bb"!#2812!#"Location"!#"22"!#"67540"!#"2"
"cc"!#"2813"!#Location!#"33"!#"67117"!#"3"
"dd"!#"2452"!#"location"!#"44"!#"67000"!#"4"
'''
df = pd.read_csv(StringIO(content), sep='#', quotechar='"', header=None)
for col in df.columns[:-1]:
try: df[col] = df[col].str[:-1]
except AttributeError: pass
try: df[col] = pd.to_numeric(df[col], errors='raise')
except ValueError: pass
print(df)
产量
0 1 2 3 4 5
0 a!#a 2811 Location "X" 11! 67000 1
1 bb 2812 Location 22 67540 2
2 cc 2813 Location 33 67117 3
3 dd 2452 location 44 67000 4
我稍微修改了您的“CSV”数据,以确保引号内的!#
未被修改
并且双引号被正确解析为单引号。