带额外逗号的列如何使用pandas读取CSV文件

36
我正在读取一个基本的CSV文件,其中列由逗号分隔,列名如下: userid, username, body 然而,body列是一个字符串,可能包含逗号。显然,这会导致问题,pandas抛出一个错误: CParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 8 有没有办法告诉pandas忽略特定列中的逗号或解决这个问题的方法?
5个回答

38

想象一下我们正在阅读您的数据框,它的名称为comma.csv:

userid, username, body
01, n1, 'string1, string2'

您可以做的一件事是使用以下代码指定列中字符串的分隔符:

df = pd.read_csv('comma.csv', quotechar="'")
在这种情况下,以'为定界符的字符串被视为整体,无论其中是否有逗号。

3
我认为他的字符串没有引号,因为如果有的话,pandas会在不使用 quotechar 的情况下识别它。 - Leb
1
@David 好的,明白了。你的数据框是“原样”提供的,还是可以对其进行一些预处理? - Fabio Lamanna
2
@David 看看这个问题(https://dev59.com/y23Xa4cB1Zd3GeqPh7rh),希望能对你有所帮助。 - Fabio Lamanna
1
@David 为什么不直接从SQL导入,可能像这样:https://dev59.com/e2ct5IYBdhLWcg3wgNgy - Leb
3
我尝试了这个例子,但对我不起作用。Python 3,pandas 0.18.0可以读取comma.csv文件,但是01变成了索引1,而username只剩下了'string1 :( - ragesz
显示剩余4条评论

18

将 usecols 和 lineterminator 参数添加到 read_csv() 函数中,其中 n 是您的列的长度。

在我的情况下:

n = 5 #define yours
df = pd.read_csv(file,
                 usecols=range(n),
                 lineterminator='\n',
                 header=None)

1
帮助了我的问题。谢谢! - szamani20

6

对于我来说,上面的代码示例都不起作用(我正在Kaggle上使用Netflix Prize数据集),但实际上,pandas 1.3.0+版本中有一个很酷的功能,即 on_bad_lines 参数,它允许您使用回调函数。这是我所做的:

def manual_separation(bad_line):
    right_split = bad_line[:-2] + [",".join(bad_line[-2:])] # All the "bad lines" where all coming from the same last column that was containing ","
    return right_split

filename = "netflix_movie_titles.csv"
df = pd.read_csv(
        filename, 
        header=None,
        encoding="ISO-8859-1",
        names = ['Movie_Id', 'Year', 'Name'], 
        on_bad_lines=manual_separation,
        engine="python",
    )

太棒了!你唯一的义务就是使用engine=python。希望这有所帮助!


1

0
首先,我没有找到任何系统性和正确的方法来解决“引号内逗号”问题。pandas=1.5.3无法正确解析它。尝试指定参数,如qoutechar、quoting、escapechar、lineterminator等。
最后,找到了两个解决方法,利用我知道逗号只能在最后一列的优势。假设以下csv内容。
userid, username, body
1, Joe, string1
2, Jim, "string21, string22"

如果您不介意第三个逗号后的部分丢失,那么请指定列数

pd.read_csv(r'c:\TEMP\to_parse.csv',usecols=range(3))

这将产生

   userid  username        body
0       1       Joe     string1
1       2       Jim   "string21

第二种解决方法更为复杂,但它能够返回含有逗号的完整字符串。原理是将前两个逗号替换成分号(您必须知道列数)。

with open(path, 'r') as f:
    fo = io.StringIO()
    data = f.readlines()
    fo.writelines(u"" + line.replace(';', ':').replace(',', ';', 2) for line in data)
    fo.seek(0)
df = pd.read_csv(fo, on_bad_lines='warn', sep=';')

或许也可以通过正则表达式实现。


嗨 @karel-marik,你可能想尝试在 read_csv 中添加 skipinitialspace=True 选项(参见这里)。这个选项帮助我使用 pandas 处理一个和你类似的示例。 - astoeriko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接