【问题标题】:Ignoring multiple commas while reading csv in pandas在熊猫中读取csv时忽略多个逗号
【发布时间】:2019-11-30 14:29:45
【问题描述】:

我正在尝试读取名称以“site_%”开头的多个文件。例如,像 site_1、site_a 这样的文件名。 每个文件都有如下数据:

Login_id, Web
1,http://www.x1.com
2,http://www.x1.com,as.php

我的 pandas df 中需要两列:Login_id 和 Web。

当我尝试读取类似 2 的记录时遇到错误。

df_0 = pd.read_csv('site_1',sep='|')
df_0[['Login_id, Web','URL']] = df_0['Login_id, Web'].str.split(',',expand=True)

我面临以下错误: ValueError: 列的长度必须与键的长度相同。

请让我知道我在哪里犯了一些严重错误以及解决问题的任何好方法。谢谢

【问题讨论】:

  • 谢谢佩德罗。我检查了。这是不同的问题。我正在尝试在第二列中读取多个带有更多逗号的文件。
  • 为什么要用|作为分隔符?
  • 嗨 rafaelc,想把它读成单列,然后分成两列。
  • 嗯,我明白了,所以你有一个不均匀的 csv 文件。当您连续拥有多个网站时,您认为数据框应该是什么样子?

标签: python python-3.x pandas


【解决方案1】:

解决方案 1:将 split 与参数 n=1expand=True 一起使用。

result= df['Login_id, Web'].str.split(',', n=1, expand=True)
result.columns= ['Login_id', 'Web']

这会产生一个包含两列的数据框,因此如果您的数据框中有更多列,则需要将其与原始数据框连接(这也适用于下一个方法)。

编辑解决方案 2:有一个更好的基于正则表达式的解决方案,它使用 pandas 函数:

result= df['Login_id, Web'].str.extract('^\s*(?P<Login_id>[^,]*),\s*(?P<URL>.*)', expand=True)

这会拆分字段并使用匹配组的名称来创建包含其内容的列。输出是:

  Login_id                       URL
0        1         http://www.x1.com
1        2  http://www.x1.com,as.php

解决方案 3:带有正则表达式的传统版本: 你可以做一些定制的事情,例如使用正则表达式:

import re
sp_re= re.compile('([^,]*),(.*)')

aux_series= df['Login_id, Web'].map(lambda val: sp_re.match(val).groups())
df['Login_id']= aux_series.str[0]
df['URL']= aux_series.str[1]

您的示例数据的结果是:

                Login_id, Web Login_id                       URL
0         1,http://www.x1.com        1         http://www.x1.com
1  2,http://www.x1.com,as.php        2  http://www.x1.com,as.php

现在您可以删除“Login_id, Web”列。

【讨论】:

  • 你确定那个正则表达式吗?第一个* 不应该在组内吗?否则它将仅匹配第一个字段的最后一个字符...&gt;&gt;&gt; re.match(r'([^,])*,(.*)', 'abc,123').groups() ('c', '123') 而在第一组中包含* 会给出预期的('abc', '123')
  • 谢谢@jottbe。我正在尝试读取多个文件,每个文件都有数百万条记录。是否有任何优化的解决方案,例如在 read_csv 本身中具有自定义函数,以便计算效率高。
  • 我不知道另一种方法。你试过这个方法吗?我猜是因为它是在 pandas 函数中实现的,所以它可能是在 C 或 C++ 中实现的。如果速度不够快,也许您可​​以更改写入文件的进程,因此它使用;| 作为分隔符,因此分隔符不会干扰 URL 列中的逗号?如果您无法更改写入过程,您仍然可以尝试使用 sed 之类的命令预处理文件(如果您在类 unix 系统上工作)。例如sed -e's/^\([^,]*\),/\1;/g' yourfile &gt; newfile(只有两列的版本)。 sed 相当快。
  • 哦,我刚刚找到了另一种方法 :-) 不知怎的,如果首先传递了n,我弄错了split 的作用(认为它从字符串的末尾开始起作用,但实际上从一开始就按照我们想要的方式工作),我更新了我的答案。所以现在你有很多方法,你可以从中选择最快的。
猜你喜欢
  • 2018-07-17
  • 2020-10-01
  • 1970-01-01
  • 2018-02-15
  • 2022-06-13
  • 2021-02-13
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多