9

我有一个格式如下的 CSV 文件:

“FieldName1”、“FieldName2”、“FieldName3”、“FieldName4”
“04/13/2010 14:45:07.008”、“7.59484916392”、“10”、“6.552373”
“04/13/2010 14:45:22.010 ", "6.55478493312", "9", "3.5378543"
...

请注意,CSV 文件中每行的开头和结尾都有双引号字符,并且该","字符串用于分隔每行内的字段。CSV 文件中的字段数可能因文件而异。

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

当我改为使用时,除了第一个和最后一个字段外delimiter='","',一切都按我的意愿工作。由于行首和行尾字符是单个双引号字符,因此这不被视为第一个和最后一个字段的有效分隔符,因此它们被读入为 eg和- 注意前导和尾随双 -分别引用字符。由于这些冗余字符,numpy 假设第一个和最后一个字段都是 String 类型;我不希望这样"04/13/2010 14:45:07.0086.552373"

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

4

1 回答 1

12

基本问题是 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.csvreader

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()看起来很接近,但它可能会将时间戳中的空间解释为列分隔符。

PScsvreader我看到的一个缺点是它不会丢弃评论。真实csv文件没有评论。

于 2010-04-19T02:17:43.220 回答