代码之家  ›  专栏  ›  技术社区  ›  monch1962

正在读取定界符为“”的numpy中的csv文件。

  •  9
  • monch1962  · 技术社区  · 15 年前

    我有一个csv文件,格式如下:

    “域名1”,“域名2”,“域名3”,“域名4”
    “2010年4月13日14:45:07.008”,“7.59484916392”,“10”,“6.552373”
    “2010年4月13日14:45:22.010”,“6.55478493312”,“9”,“3.5378543”

    注意,在csv文件的每一行的开头和结尾都有双引号字符,并且 "," 字符串用于分隔每行中的字段。csv文件中的字段数因文件而异。

    当我试图通过以下方式将其读成numpy via时:
    import numpy as np
    data = np.genfromtxt(csvfile, dtype=None, delimiter=',', names=True)
    所有数据都作为字符串值读取,并由双引号字符包围。不是不合理的,但对我没有太大的用处,因为我必须返回并将每一列转换为正确的类型

    当我使用 delimiter='","' 相反,一切都按我的意愿工作, 除了 第一个和最后一个字段。由于行首字符和行尾字符是单双引号字符,因此这不被视为第一个和最后一个字段的有效分隔符,因此它们作为例如读取。 "04/13/2010 14:45:07.008 6.552373" -分别注意前导和尾随双引号字符。由于这些冗余字符,numpy假定第一个和最后一个字段都是字符串类型;我不希望是这种情况。

    有没有一种方法可以指示numpy按照我喜欢的方式读取格式化的文件,而不必在初始读取后返回并“修复”numpy数组的结构?

    1 回复  |  直到 15 年前
        1
  •  12
  •   Mike DeSimone    15 年前

    基本的问题是numpy不理解去掉引号的概念(而 csv 模块有)。当你说 delimiter='","' ,您告诉numpy列分隔符实际上是一个带引号的逗号,也就是说,引号是围绕逗号的,而不是值,所以您在第一列和最后一列上得到的额外引号是预期的。

    查看函数文档,我想您需要设置 converters 为您除去引号的参数(默认值不为):

    import re
    import numpy as np
    
    fieldFilter = re.compile(r'^"?([^"]*)"?$')
    def filterTheField(s):
        m = fieldFilter.match(s.strip())
        if m:
            return float(m.group(1))
        else:
            return 0.0 # or whatever default
    
    #...
    
    # Yes, sorry, you have to know the number of columns, since the NumPy docs
    # don't say you can specify a default converter for all columns.
    convs = dict((col, filterTheField) for col in range(numColumns))
    data = np.genfromtxt(csvfile, dtype=None, delimiter=',', names=True, 
        converters=convs)
    

    或者放弃 np.genfromtxt() csv.csvreader 将文件的内容作为字符串列表一次一行,然后迭代元素并构建矩阵:

    reader = csv.csvreader(csvfile)
    result = np.array([[float(col) for col in row] for row in reader])
    # BTW, column headings are in reader.fieldnames at this point.
    

    编辑:好的,所以看起来你的文件不是都是浮动的。在这种情况下,您可以设置 convs 根据需要 genfromtxt 或创建转换函数的向量 csv.csv阅读器 案例:

    reader = csv.csvreader(csvfile)
    converters = [datetime, float, int, float]
    result = np.array([[conv(col) for col, conv in zip(row, converters)] 
        for row in reader])
    # BTW, column headings are in reader.fieldnames at this point.
    

    编辑2:好的,变量列计数…你的数据源只是想让生活变得困难。幸运的是,我们可以使用 magic

    reader = csv.csvreader(csvfile)
    result = np.array([[magic(col) for col in row] for row in reader])
    

    …哪里 magic() 只是一个名字,我为了一个功能从我的头上取了下来。(通灵!)

    最坏的情况下,可能是:

    def magic(s):
        if '/' in s:
            return datetime(s)
        elif '.' in s:
            return float(s)
        else:
            return int(s)
    

    也许numpy有一个函数,它接受一个字符串并返回一个类型正确的元素。 numpy.fromstring() 看起来很近,但它可能会将时间戳中的空间解释为列分隔符。

    另一个缺点是 csvreader 我明白了,它并没有抛弃评论;真的 猪瘟病毒 文件没有注释。