填充numpy数组的Pythonic方法

填充numpy数组的Pythonic方法,python,arrays,numpy,Python,Arrays,Numpy,我发现自己正在使用csv阅读器和for循环对每一行进行迭代,从而解析大量数据文件(通常是.csv文件或类似文件)。例如,数据通常是一个浮动表 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(

我发现自己正在使用csv阅读器和for循环对每一行进行迭代,从而解析大量数据文件(通常是.csv文件或类似文件)。例如,数据通常是一个浮动表

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数据文件。)有
numpy.loadtxt

X = numpy.loadtxt('somefile.csv', delimiter=',')


编辑:对于numpy数组的列表

X = [scipy.array(line.split(','), dtype='float') 
     for line in open('somefile.csv', 'r')]

我认为很难在你现有的基础上提高很多。Python列表的构建和附加成本相对较低;NumPy数组的创建成本更高,而且根本不提供
.append()
方法。因此,最好的办法是像您已经在做的那样构建列表,然后在时机成熟时强制使用
np.array()

有几个要点:

  • 使用
    []
    创建列表比调用
    list()
    稍微快一点。这是程序运行时的一小部分,您可以随意忽略这一点

  • 当您实际上不使用循环索引时,可以使用变量名
    \uu
    来记录这一点

  • 迭代一个序列通常比查找序列的长度、构建一个
    范围()
    ,然后对序列进行大量索引要好。如果还需要索引,可以使用
    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))

为了有效地将数据加载到NumPyarraya,我喜欢NumPy的fromiter函数

这方面的优势:

  • 流式装载

  • 预先指定reesult数组的数据类型,以及

  • 预分配空输出数组,然后填充该数组 从伊特拉布河来的小溪

第一个是固有的——fromiter只接受iterable形式的数据输入——最后两个是通过传递给fromiter、dtype和count的第二个和第三个参数来管理的

如果不想使用iterable加载数据,仍然可以使用NumPy函数emptyempty_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创建一个空的(预先分配的)数组,然后只传入所需的形状。此函数与类似的空函数相比,让您传入数据类型:

>>> 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])

我以前考虑过这一点,但它有一些问题,特别是它要求数组中的行长度相同。虽然我的小代码片段假设相同,但它并不总是发生(例如,空行表示数据收集突发之间的中断)。“NumPy…根本不提供.append()方法”NumPy确实有一个append方法。它的工作原理与python append差不多,只是没有“就位”。@doug:
a=np.array(范围(3))
成功。然后,
a.append(4)
给出消息
AttributeError:'numpy.ndarray'对象没有属性'append'
。如果NumPy数组有一个
.append()
方法,那么我在这里做错了什么?那么试试这个:a=NP.random.randint(0,10,5);a=NP.append(a[2,3])。所以NumPy有一个append函数而不是append方法——这使得您在上面的答案中的语句完全正确!在回答问题之前,我通常会先尝试一下。但是我没有想到要寻找一个非方法
append()
函数!
>>> 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])