在Python中使用scipy/numpy解析字母数字CSV的可靠方法
我一直在寻找一种好的、灵活的方法来解析Python中的CSV文件,但标准的选项似乎都不太合适。我有点想自己写一个,但我觉得结合numpy/scipy和csv模块的某些功能就能满足我的需求,所以我不想重复造轮子。
我希望能有一些标准功能,比如可以指定分隔符、是否有表头、跳过多少行、注释的分隔符、忽略哪些列等等。我最缺少的一个功能是能够以一种优雅的方式解析CSV文件,同时处理字符串数据和数字数据。我的很多CSV文件中有些列包含字符串(长度不一定相同)和数字数据。我希望能对这些数字数据使用numpy数组的功能,同时也能访问字符串。例如,假设我的文件看起来是这样的(想象一下列是用制表符分隔的):
# my file
name favorite_integer favorite_float1 favorite_float2 short_description
johnny 5 60.2 0.52 johnny likes fruitflies
bob 1 17.52 0.001 bob, bobby, robert
data = loadcsv('myfile.csv', delimiter='\t', parse_header=True, comment='#')
我希望能以两种方式访问数据:
作为一个值的矩阵:对我来说,获取一个numpy.array很重要,这样我可以轻松地转置并访问数字列。在这种情况下,我想做类似这样的事情:
floats_and_ints = data.matrix
floats_and_ints[:, 0] # 访问整数
floats_and_ints[:, 1:3] # 访问一些浮点数
transpose(floats_and_ints) # 等等..
作为一个类似字典的对象,我不需要知道表头的顺序:我也希望能按表头的顺序访问数据。例如,我想这样做:
data['favorite_float1'] # 获取表头为"favorite_float1"的列的所有值
data['name'] # 获取所有行的名字
我不想知道favorite_float1是表格中的第二列,因为这可能会改变。
对我来说,能够遍历行并按名称访问字段也很重要。例如:
for row in data:
# print names and favorite integers of all
print "Name: ", row["name"], row["favorite_int"]
(1)中的表示方式暗示了numpy.array,但据我所知,这种方式对字符串处理得不好,需要我提前指定数据类型和表头标签。
(2)中的表示方式暗示了字典列表,这也是我一直在使用的。然而,这对于有两个字符串字段而其他列都是数字的CSV文件来说,真的很糟糕。对于数字值,你确实希望能够访问矩阵表示,并将其作为numpy.array进行操作。
有没有一种结合csv/numpy/scipy功能的方式,可以兼顾这两种灵活性?对此的任何建议都将非常感激。
总之,主要功能有:
- 标准的指定分隔符、跳过的行数、忽略的列等的能力。
- 能够获取数据的numpy.array/矩阵表示,以便可以操作数字值。
- 能够按表头名称提取列和行(如上例所示)。
4 个回答
numpy.genfromtxt() 是一个用来从文本文件中读取数据的函数。它可以处理各种格式的数据,比如数字、字符串等。这个函数特别适合处理那些有缺失值的数据,因为它可以自动识别并处理这些缺失的部分。
使用这个函数时,你只需要告诉它文件的路径,数据的分隔符(比如逗号、空格等),以及你想要读取的数据类型。这样,numpy就会把文件里的数据读进来,变成一个可以在程序中使用的数组。
总之,numpy.genfromtxt() 是一个非常方便的工具,可以帮助你轻松地从文本文件中获取数据,特别是当数据格式不太规则或者有缺失值的时候。
matplotlib.mlab.csv2rec
这个函数会返回一个 numpy
的 recarray
,这意味着你可以对这个数据做很多 numpy
数组能做的事情。每一行数据都是 record
类型的实例,你可以像用元组一样来访问它们,但它们也有自动命名的属性,这些属性对应你数据中的列名:
rows = matplotlib.mlab.csv2rec('data.csv')
row = rows[0]
print row[0]
print row.name
print row['name']
csv2rec
还能够理解“带引号的字符串”,这点不同于 numpy.genfromtext
。
总的来说,我觉得 csv2rec
结合了 csv.reader
和 numpy.genfromtext
的一些最佳功能。
看看这个pandas,它是建立在numpy
之上的。这里有一个简单的例子:
In [7]: df = pd.read_csv('data.csv', sep='\t', index_col='name')
In [8]: df
Out[8]:
favorite_integer favorite_float1 favorite_float2 short_description
name
johnny 5 60.20 0.520 johnny likes fruitflies
bob 1 17.52 0.001 bob, bobby, robert
In [9]: df.describe()
Out[9]:
favorite_integer favorite_float1 favorite_float2
count 2.000000 2.000000 2.000000
mean 3.000000 38.860000 0.260500
std 2.828427 30.179317 0.366988
min 1.000000 17.520000 0.001000
25% 2.000000 28.190000 0.130750
50% 3.000000 38.860000 0.260500
75% 4.000000 49.530000 0.390250
max 5.000000 60.200000 0.520000
In [13]: df.ix['johnny', 'favorite_integer']
Out[13]: 5
In [15]: df['favorite_float1'] # or attribute: df.favorite_float1
Out[15]:
name
johnny 60.20
bob 17.52
Name: favorite_float1
In [16]: df['mean_favorite'] = df.mean(axis=1)
In [17]: df.ix[:, 3:]
Out[17]:
short_description mean_favorite
name
johnny johnny likes fruitflies 21.906667
bob bob, bobby, robert 6.173667