我刚刚开始使用 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,因此它们很有吸引力。

有帮助吗?

解决方案

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

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

  • 如果你想进一步优化它,你可以将你的值存储到 numpy 数组列表中,这样你只需执行一次 python list -> numpy 数组转换。
  • 如果你发现这仍然太慢,请尝试使用psycho来优化python循环。
  • 如果这仍然太慢,请尝试使用 赛通 与 numpy 模块一起。这 教程 声称图像处理速度显着提高。或者简单地在 Cython 中对整个 std 函数进行编程(请参阅 对于带有 sum 函数的基准和示例)
  • Cython 的替代方案是使用 斯威格numpy.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)

其他提示

虽然这里已经提出了一些相当合理的想法,但我相信以下内容值得一提。

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

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

使用 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)

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.])
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top