Pandas read_csv不解释quotechar

时间:2017-08-18 15:45:53

标签: python pandas csv quotes

使用以下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()的解决方案(我无法更改!#,而"非常重要,因为!#可以找到一栏。

5 个答案:

答案 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”数据,以确保引号内的!#未被修改 并且双引号被正确解析为单引号。