如何在pandas.read_csv()

时间:2018-09-03 16:21:22

标签: python-3.x pandas

我有一个稍微破损的CSV文件,我想对其进行预处理,然后再使用pandas.read_csv()进行读取,即对其进行一些搜索/替换。

我试图打开文件并在生成器中进行预处理,然后将其交给read_csv():

    def in_stream():
    with open("some.csv") as csvfile:
        for line in csvfile:
            l = re.sub(r'","',r',',line)
            yield l

    df = pd.read_csv(in_stream())

可悲的是,这只会引发

ValueError: Invalid file path or buffer object type: <class 'generator'>

尽管,在查看Panda的源代码时,我希望它能够在迭代器(即生成器)上工作。

我只发现了此[article](Using a custom object in pandas.read_csv()),概述了如何将生成器包装到类似文件的对象中,但是它似乎仅适用于字节模式的文件。

因此,最后我要寻找一种模式来构建一个打开文件的管道,逐行读取文件,允许进行预处理,然后将其输入例如pandas.read_csv()。

2 个答案:

答案 0 :(得分:0)

这是一个适用于较小CSV文件的解决方案。首先将所有行读入内存,进行处理和连接。对于较大的文件,这可能会产生不好的效果。

import re
from io import StringIO
import pandas as pd

with open('file.csv') as file:
    lines = [re.sub(r'","', r',', line) for line in file]

df = pd.read_csv(StringIO('\n'.join(lines)))

答案 1 :(得分:0)

在进一步研究了Pandas的来源之后,很明显,它不仅需要迭代,而且还希望它是一个文件,通过具有read方法(inference.py中的is_file_like())来表示。

所以,我用旧方法建造了发电机

class InFile(object):
def __init__(self, infile):
    self.infile = open(infile)

def __next__(self):
    return self.next()

def __iter__(self):
    return self

def read(self, *args, **kwargs):
    return self.__next__()

def next(self):
    try:
        line: str = self.infile.readline()
        line = re.sub(r'","',r',',line) # do some fixing
        return line
    except:
        self.infile.close()
        raise StopIteration

这在pandas.read_csv()中有效:

df = pd.read_csv(InFile("some.csv"))

对我来说,这看起来超级复杂,我想知道是否有更好的解决方案(→更优雅)。