8

我刚从 NumPy 开始,所以我可能会遗漏一些核心概念......

从值是列表的字典创建 NumPy 数组的最佳方法是什么?

像这样的东西:

d = { 1: [10,20,30] , 2: [50,60], 3: [100,200,300,400,500] }

应该变成这样的东西:

data = [
  [10,20,30,?,?],
  [50,60,?,?,?],
  [100,200,300,400,500]
]

我将对每一行做一些基本的统计,例如:

deviations = numpy.std(data, axis=1)

问题:

  • 从字典创建 numpy.array 的最佳/最有效方法是什么?字典很大;几百万把钥匙,每把钥匙大约有 20 件物品。

  • 每个“行”的值的数量是不同的。如果我理解正确 numpy 想要统一大小,那么我应该为缺失的项目填写什么以使 std() 满意?

更新:我忘了提一件事——虽然 Python 技术是合理的(例如,循环数百万个项目很快),但它仅限于单个 CPU。Numpy 操作可以很好地扩展到硬件并使用所有 CPU,因此它们很有吸引力。

4

3 回答 3

8

您无需创建 numpy 数组即可调用 numpy.std()。您可以在字典的所有值上循环调用 numpy.std() 。该列表将即时转换为 numpy 数组以计算标准变化。

这种方法的缺点是主循环将在 python 中而不是在 C 中。但我想这应该足够快:你仍然会以 C 的速度计算 std,并且你会节省大量内存,因为你不会必须在具有可变大小数组的地方存储 0 个值。

  • 如果您想进一步优化这一点,您可以将您的值存储到一个 numpy 数组列表中,以便您只执行一次 python 列表 -> numpy 数组转换。
  • 如果你发现这仍然太慢,尝试使用 Psycho 来优化 python 循环。
  • 如果这仍然太慢,请尝试将Cython与 numpy 模块一起使用。本教程声称图像处理的速度得到了令人印象深刻的改进。或者简单地在 Cython 中编写整个 std 函数(有关sum 函数的基准和示例,请参见this )
  • Cython 的替代方法是将SWIGnumpy.i一起使用。
  • 如果您只想使用 numpy 并在 C 级别计算所有内容,请尝试将所有相同大小的记录分组到不同的数组中,并在每个数组上调用 numpy.std()。它应该类似于以下示例。

复杂度为 O(N) 的示例:

import numpy
list_size_1 = []
list_size_2 = []
for row in data.itervalues():
    if len(row) == 1:
      list_size_1.append(row)
    elif len(row) == 2:
      list_size_2.append(row)
list_size_1 = numpy.array(list_size_1)
list_size_2 = numpy.array(list_size_2)
std_1 = numpy.std(list_size_1, axis = 1)
std_2 = numpy.std(list_size_2, axis = 1)
于 2009-03-02T08:02:56.287 回答
2

虽然这里已经有一些非常合理的想法,但我相信以下值得一提。

用任何默认值填充缺失的数据会破坏统计特征(std 等)。显然这就是为什么 Mapad 提出了将相同大小的记录分组的好技巧。它的问题(假设手头没有任何关于记录长度的先验数据)是它涉及比直接解决方案更多的计算:

  1. 至少O(N*logN) 'len' 调用和比较以使用有效算法进行排序
  2. O(N)检查列表的第二种方式以获得组(它们在“垂直”轴上的开始和结束索引)

使用 Psyco 是个好主意(它非常容易使用,所以一定要试一试)。

似乎最佳方法是采用 Mapad 在项目符号 #1 中描述的策略,但进行了修改 - 不是生成整个列表,而是遍历字典,将每一行转换为 numpy.array 并执行所需的计算。像这样:

for row in data.itervalues():
    np_row = numpy.array(row)    
    this_row_std = numpy.std(np_row)
    # compute any other statistic descriptors needed and then save to some list

在任何情况下,python 中的几百万个循环都不会像预期的那样花费很长时间。此外,这看起来不像是例行计算,所以谁在乎它是否需要额外的秒/分钟,如果它偶尔运行一次甚至只是一次。


Mapad 建议的通用变体:

from numpy import array, mean, std

def get_statistical_descriptors(a):
    if ax = len(shape(a))-1
    functions = [mean, std]
    return f(a, axis = ax) for f in functions


def process_long_list_stats(data):
    import numpy

    groups = {}

    for key, row in data.iteritems():
        size = len(row)
        try:
            groups[size].append(key)
        except KeyError:
            groups[size] = ([key])

    results = []

    for gr_keys in groups.itervalues():             
        gr_rows = numpy.array([data[k] for k in gr_keys])       
        stats = get_statistical_descriptors(gr_rows)                
        results.extend( zip(gr_keys, zip(*stats)) )

    return dict(results)
于 2009-03-02T20:36:03.230 回答
0

numpy 字典

您可以使用结构化数组来保留通过键(如字典)来寻址 numpy 对象的能力。

import numpy as np


dd = {'a':1,'b':2,'c':3}
dtype = eval('[' + ','.join(["('%s', float)" % key for key in dd.keys()]) + ']')
values = [tuple(dd.values())]
numpy_dict = np.array(values, dtype=dtype)

numpy_dict['c']

现在将输出

array([ 3.])
于 2012-07-23T20:11:50.730 回答