我发现自己使用csv阅读器解析了大量数据文件(通常是.csv文件或类似文件),并使用for循环迭代每一行。例如,数据通常是一个浮动表。
reader = csv.reader(open('somefile.csv'))
header = reader.next()
res_list = [list() for i in header]
for line in reader:
for i in range(len(line)):
res_list[i].append(float(line[i]))
result_dict = dict(zip(header,res_list)) #so we can refer by column title
这是一个填充的好方法,所以我将每个列作为一个单独的列表,但是,我更希望项目列表(和嵌套列表)的默认数据容器是numpy数组,因为99次超过100个数字得到泵入各种处理脚本/功能,并具有numpy列表的力量使我的生活更轻松。
numpy append(arr, item)
不会就地附加,因此需要为表中的每个点重新创建数组(这是缓慢且不必要的)。我也可以遍历数据列列表并在完成之后将它们包装成一个数组(这就是我一直在做的事情),但有时它不是那么明确地切割时我已经完成了对文件的解析,并且可能需要稍后将内容添加到列表中。
我想知道是否有一些不那么乏味的方法(使用过度使用的短语“pythonic”)以类似的方式处理数据表,或者动态填充数组(底层容器是列表)并且不会一直复制数组。
(另一个注意事项:通常人们使用列来组织数据,但是如果读者合并了read_column参数,那么csv
会读入行(是的,我知道它不会超级高效) ,我想很多人都会避免像上面这样的锅炉板代码来解析csv数据文件。)
答案 0 :(得分:7)
有numpy.loadtxt
:
X = numpy.loadtxt('somefile.csv', delimiter=',')
编辑:获取numpy数组列表
X = [scipy.array(line.split(','), dtype='float')
for line in open('somefile.csv', 'r')]
答案 1 :(得分:2)
我认为很难改善你所拥有的东西。 Python列表构建和追加相对便宜; NumPy数组的创建成本更高,并且根本不提供.append()
方法。因此,最好的办法是按照您现在的方式构建列表,然后在时机成文时强制转移到np.array()
。
一些小问题:
使用[]
创建列表比调用list()
稍快一些。这是程序运行时的一小部分,您可以随意忽略这一点。
如果您实际上没有使用循环索引,则可以使用_
作为变量名来记录此内容。
迭代序列通常比找到序列的长度更好,构建一个range()
,然后对序列进行大量索引。如果您还需要索引,可以使用enumerate()
获取索引。
将它们放在一起,我认为这是一个稍微改进的版本。但它与你的原版几乎没有变化,我想不出任何真正好的改进。
reader = csv.reader(open('somefile.csv'))
header = reader.next()
res_list = [ [] for _ in header]
for row in reader:
for i, val in enumerate(row):
res_list[i].append(float(val))
# build dict so we can refer by column title
result_dict = dict((n, res_list[i]) for i, n in enumerate(header))
答案 2 :(得分:2)
为了有效地将数据加载到 NumPy 数组,我喜欢NumPy的 fromiter 功能。
在这方面的优势:
流式加载,
预先指定reesult数组的数据类型,
预先分配空输出数组,然后填充 来自可迭代的流。
第一个是固有的 - fromiter 只接受以可迭代形式输入的数据 - 后两个通过传递给fromiter的第二个和第三个参数进行管理, dtype,和计数的
>>> import numpy as NP
>>> # create some data to load:
>>> import random
>>> source_iterable = (random.choice(range(100)) for c in range(20))
>>> target = NP.fromiter(source_iterable, dtype=NP.int8, count=v.size)
>>> target
array([85, 28, 37, 4, 23, 5, 47, 17, 78, 40, 28, 5, 69, 47, 15, 92,
41, 33, 33, 98], dtype=int8)
如果您不想使用iterable加载数据,您仍然可以使用NumPy函数清空 为目标数组预分配内存,并且的 empty_like 强>
>>> source_vec = NP.random.rand(10)
>>> target = NP.empty_like(source_vec)
>>> target[:] = source_vec
>>> target
array([ 0.5472, 0.5085, 0.0803, 0.4757, 0.4831, 0.3054, 0.1024,
0.9073, 0.6863, 0.3575])
或者,你可以通过调用 empty 创建一个空的(预分配的)数组,然后只传入你想要的形状。与 empty_like 相比,此功能让您传递数据类型:
>>> target = NP.empty(shape=s.shape, dtype=NP.float)
>>> target
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
>>> target[:] = source
>>> target
array([ 0.5472, 0.5085, 0.0803, 0.4757, 0.4831, 0.3054, 0.1024,
0.9073, 0.6863, 0.3575])