使用numpy.genfromtxt读取包含逗号字符串的csv文件

41

我正在尝试使用numpy.genfromtxt读取一个csv文件,但其中一些字段是包含逗号的字符串。这些字符串被放在引号中,但是numpy没有将引号识别为单个字符串。例如,在数据文件“t.csv”中:

2012, "Louisville KY", 3.5
2011, "Lexington, KY", 4.0

代码

np.genfromtxt('t.csv', delimiter=',')

输出以下错误:

 

ValueError:检测到一些错误!第2行(实际得到4列,而不是3列)

我正在寻找的数据结构为:

array([['2012', 'Louisville KY', '3.5'],
       ['2011', 'Lexington, KY', '4.0']], 
      dtype='|S13')

在查阅文档后,我没有看到任何处理这个问题的选项。是否有一种使用numpy的方法来处理它,或者我只需要使用csv模块读入数据然后将其转换为numpy数组?


你能发布更完整的CSV文件吗?我想我知道如何解决你的问题 ;) - Eiyrioü von Kauyf
你应该将CSV文件中的分隔符从,更改为;,例如... - Saullo G. P. Castro
@SaulloCastro:我不能这样做,因为我的真实数据更加混乱,并且包含带有;和/或任何其他字符的字符串 - 这只是一个玩具示例。我正在寻找一种更通用的解决方案。 - CraigO
正如我所提到的,这只是一个玩具示例,用来说明问题,但我认为它具备了所有必要的特征。你具体在寻找什么? - CraigO
5个回答

26
你可以使用pandas(在科学Python中处理数据框架(异构数据)的默认库)来完成此操作。它的read_csv可以处理此操作。从文档中得知:

quotechar : string

The character to used to denote the start and end of a quoted item. Quoted items 
can include the delimiter and it will be ignored.
默认值为"。例如:
In [1]: import pandas as pd

In [2]: from StringIO import StringIO

In [3]: s="""year, city, value
   ...: 2012, "Louisville KY", 3.5
   ...: 2011, "Lexington, KY", 4.0"""

In [4]: pd.read_csv(StringIO(s), quotechar='"', skipinitialspace=True)
Out[4]:
   year           city  value
0  2012  Louisville KY    3.5
1  2011  Lexington, KY    4.0

这里的技巧是你还需要使用skipinitialspace=True来处理逗号分隔符后面的空格。
除了强大的csv读取器外,我还强烈建议您在处理异构数据时使用pandas(您给出的numpy示例输出都是字符串,尽管您可以使用结构化数组)。

太棒了,运行得非常顺畅。我听说过 pandas,但以前从未尝试过 - 这似乎是一个很好的机会。顺便说一下,我本来想用 np.recfromcsv 来获取结构化的 numpy 数组,只是为了让我的初始示例保持简单。 - CraigO

15
使用额外的逗号会导致np.genfromtxt无法处理。
一个简单的解决方法是使用Python的csv模块中的csv.reader()读取文件到列表中,然后将其转换为numpy数组(如果需要)。
如果您真的想使用np.genfromtxt,请注意它可以接受迭代器而不是文件,例如np.genfromtxt(my_iterator, ...)。因此,您可以将csv.reader包装在迭代器中,并将其传递给np.genfromtxt
这大概是这样的:
import csv
import numpy as np

np.genfromtxt(("\t".join(i) for i in csv.reader(open('myfile.csv'))), delimiter="\t")

这基本上只替换适当的逗号为制表符。


嗯,我明白你的意思,但是我试了一下还是没能完全搞定。不管怎样,今天我打算使用 pandas。无论如何,还是谢谢你。 - CraigO

6
如果您正在使用numpy,您可能希望使用numpy.ndarray进行操作。这将为您提供一个numpy.ndarray:
import pandas
data = pandas.read_csv('file.csv').as_matrix()

Pandas将正确处理“Lexington,KY”的情况。

1
请注意,如果您这样做,第一行可能会丢失。第一行被视为数据框的列标签。 - Binu Jasim
2
as_matrix()函数很快将不再被支持,请使用.values代替。 - efthimio

2
创建一个更好的函数,结合了标准 csv 模块 和 Numpy 的 recfromcsv 功能。例如,csv 模块具有良好的方言控制和自定义方言、引号、转义字符等功能,这些功能可以添加到下面的示例中。
下面的示例函数 genfromcsv_mod 读取类似于 Microsoft Excel 的复杂 CSV 文件,其中可能包含在引号字段内的逗号。在内部,该函数具有生成器函数,该函数使用制表符分隔符重写每一行。
import csv
import numpy as np

def recfromcsv_mod(fname, **kwargs):
    def rewrite_csv_as_tab(fname):
        with open(fname, newline='') as fp:
            dialect = csv.Sniffer().sniff(fp.read(1024))
            fp.seek(0)
            for row in csv.reader(fp, dialect):
                yield "\t".join(row)
    return np.recfromcsv(
        rewrite_csv_as_tab(fname), delimiter="\t", encoding=None, **kwargs)

# Use it to read a CSV file into a record array
x = recfromcsv_mod("t.csv", case_sensitive=True)

我认为应该使用open(fname, 'r'),否则会出现将字节传递而不是字符串的错误。 - Guillaume
@Guillaume 谢谢,这是为Python 2准备的,但已更新为Python 3。 - Mike T

0
你可以尝试这段代码。我们使用np.genfromtext()方法读取.csv文件。 代码:
myfile = np.genfromtxt('MyData.csv', delimiter = ',')
myfile = myfile.astype('int64')
print(myfile)

输出:

[[ 1  1  1  1  1  1  1  1  1  1  1]
 [ 3  3  3  3  3  3  3  3  3  3  3]
 [ 3  3  3  3  3  3  3  3  3  3  3]
 [ 4  4  4  4  4  4  4  4  4  4  4]
 [ 5  5  5  5  5  5  5  5  5  5  5]
 [ 6  6  6  6  6  6  6  6  6  6  6]
 [ 7  7  7  7  7  7  7  7  7  7  7]
 [ 8  8  8  8  8  8  8  8  8  8  8]
 [ 9  9  9  9  9  9  9  9  9  9  9]
 [10 10 10 10 10 10 10 10 10 10 10]
 [11 11 11 11 11 11 11 11 11 11 11]
 [12 12 12 12 12 12 12 12 12 12 12]
 [13 13 13 13 13 13 13 13 13 13 13]
 [14 14 14 14 14 14 14 14 14 14 14]
 [15 15 15 15 15 15 15 15 15 15 15]
 [16 17 18 19 20 21 22 23 24 25 26]]
输入文件"MyData.csv"

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接