坏数据上的 Pandas 数据帧 read_csv
Posted
技术标签:
【中文标题】坏数据上的 Pandas 数据帧 read_csv【英文标题】:Pandas dataframe read_csv on bad data 【发布时间】:2016-01-31 03:55:13 【问题描述】:我想读取一个非常大的 csv(无法在 excel 中打开并轻松编辑),但在第 100,000 行附近的某处,有一行有一个额外的列导致程序崩溃。这一行出错了,所以我需要一种方法来忽略它是一个额外的列的事实。大约有 50 列,因此对标题进行硬编码并使用名称或 usecols 是不可取的。我也可能会在其他 csv 中遇到这个问题并想要一个通用的解决方案。不幸的是,我在 read_csv 中找不到任何东西。代码就这么简单:
def loadCSV(filePath):
dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1', nrows=1000)
datakeys = dataframe.keys();
return dataframe, datakeys
【问题讨论】:
除上述之外,使用warn_bad_lines=True
可能会进一步帮助诊断有问题的行。
【参考方案1】:
这是我解决这些问题的方法,它很慢但效果很好, 简单地说,只需将 CSV 文件读取为 txt 文件,然后遍历每一行。 如果“,”逗号小于它应该跳过该行。 最终确保正确的线路安全。
def bad_lines(path):
import itertools
num_columns = []
lines = ""
for i in range(10,50,5):
content = open(path).readlines(i)[0]
if (content.count("'") == 0) and (content.count('"') == 0):
num_columns.append(content.count(","))
if len(set(num_columns)) == 1:
for line in itertools.islice(open(path), 0, None):
if line.count(",") >= num_columns[0]:
lines = lines + line
text_file = open("temp.txt", "w")
n = text_file.write(lines)
text_file.close()
return("temp.txt")
【讨论】:
有很多更好的方法来处理这个问题,因为你的答案很容易出错。请考虑修改或删除此答案。【参考方案2】:要获取有关导致错误的行的信息,请尝试使用 error_bad_lines=False
和 warn_bad_lines=True
的组合:
dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1', nrows=1000,
warn_bad_lines=True, error_bad_lines=False)
error_bad_lines=False
跳过导致错误的行,warn_bad_lines=True
打印错误详细信息和行号,如下所示:
'Skipping line 3: expected 4 fields, saw 3401\nSkipping line 4: expected 4 fields, saw 30...'
如果您想保存警告消息(即用于进一步处理),那么您也可以将其保存到文件中(使用contextlib
):
import contextlib
with open(r'D:\Temp\log.txt', 'w') as log:
with contextlib.redirect_stderr(log):
dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1',
warn_bad_lines=True, error_bad_lines=False)
【讨论】:
【参考方案3】:通过error_bad_lines=False
跳过错误的行:
error_bad_lines : 布尔值,默认 True Lines 字段太多 (例如,逗号太多的 csv 行)默认情况下会导致 引发异常,并且不会返回任何 DataFrame。如果为假, 那么这些“坏行”将从 DataFrame 中删除,即 回来。 (仅对 C 解析器有效)
【讨论】:
我忘了提到那个。它适用于我目前想做的事情,但在路上我会想要没有附带额外价值的行。 另一种方法是读取单行以获得正确的列数,然后再次重新读取以仅读取这些列,例如cols = pd.read_csv(file, nrows=1).columns df = pd.read_csv(file, usecols=cols)
然后这将忽略我认为该错误行的附加列尝试并告诉我它是否适合您
@Fonti:truncate_bad_lines
没有选项。这样做将是一个不好的做法。您假设您事先知道数据为什么不好(它附加了一个额外的值)。但是如果它的列太少怎么办?如果插入而不是附加额外的值怎么办?做这样的事情是一个吸虫器。
实际上我刚刚尝试过,但它不起作用,我认为您需要传递 error_bad_lines=False
并解析警告以获取行号并使用 @987654326 读取这些行@
@Edchum 这很奇怪,我认为它对我有用。我没有在该行出现错误,而是出现了内存错误(超过 400 万行)。另一条需要解决的鱼。以上是关于坏数据上的 Pandas 数据帧 read_csv的主要内容,如果未能解决你的问题,请参考以下文章
如何将 pandas 时间戳添加到数据帧 post read_csv
6.5 GB 文件上的 Pandas read_csv 消耗超过 170 GB RAM