【问题标题】:Numpy array (matrix) with one axis indices being strings一个轴索引为字符串的 Numpy 数组(矩阵)
【发布时间】:2015-03-23 12:18:05
【问题描述】:

在 numpy 中可以创建一个矩阵并使用方便的切片表示法

arr=np.array([[1,2,3], [4,5,6], [7, 8, 9], [10,11,12]])
print (arr[2, :])
print (arr[1:2, 2])

这可以扩展到N维。

但是现在,如果我希望拥有相同的东西,但是一个轴不是数字轴,而是基于字符串的轴,该怎么办?所以索引一个元素就像:

print(arr["cylinder", :, :]) #prints all cylinders
print(arr["sphere", 4, 100]) #prints sphere of 4 radius, 100 bar
print(arr[:, 4, 100]) #prints every shape with 4 radius 100 bar

我可以为每个“组合”(所有形状、特定半径、特定压力……所有形状、所有半径、特定压力……特定形状、特定半径、特定压力)。一个独特的功能,但这是不可行的,那么我该如何创建呢?

目前,所有内容都存储为字典中的字典(尤其是因为只使用了半径和压力值)。如果可以将底层存储保存为字典的字典 - 但添加切片/索引运算符,那将是黄金!


当前代码(是的,我确实有想法研究 kwargs 以使当前代码库更好地添加新点) - 这只是为了防止“NP”问题而添加:
class all_measurements(object):
    def __init__(self):
        self.measurements = {}

    def add_measurement(self, measurement):
        shape = measurement.shape
        size = measurement.size
        pressure = measurement.pressure
        fname = measurement.filename
        if shape in self.measurements:
            shape_dict = self.measurements[shape]
        else:
            shape_dict = {}
            self.measurements[shape] = shape_dict

        if size in shape_dict:
            size_dict = shape_dict[size]
        else:
            size_dict ={}
            shape_dict[size] = size_dict

        if pressure in size_dict:
            pressure_dict = size_dict[pressure]
        else:
            pressure_dict = {}
            size_dict[pressure] = pressure_dict

        if fname in pressure_dict:
            print("adding same file twice!")

        pressure_dict[fname] = measurement

    def get_measurements(self, shape = None, size = None, pressure = None, fname = None):
        current_dict = self.measurements
        if shape is None:
            return current_dict
        if shape in current_dict:
            current_dict = current_dict[shape]
        else:
            return None

        if size is None:
            return current_dict
        if size in current_dict:
            current_dict = current_dict[size]
        else:
            return None

        if pressure is None:
            return current_dict
        if pressure in current_dict:
            current_dict = current_dict[pressure]
        else:
            return None

        if fname is None:
            return current_dict
        if fname in current_dict:
            return current_dict[fname]
        else:
            return None

【问题讨论】:

  • 我认为您将映射与索引混合在一起。除了结构化数组的字段名称外,索引只计算行和/或列。它们没有标签、数字或其他标签。
  • 您可以将__getitem____getslice__ 方法添加到您的类中以获取索引语法。当然,解释索引或切片并返回正确的项目是您的责任。

标签: python numpy dictionary matrix


【解决方案1】:

我认为您正在寻找结构化数组,请参阅here

例子:

>>> import numpy as np

>>> a = np.zeros(10,dtype={'names':['a','b','c'],'formats':['f64','f64','f64']})

# write some data in a
>>> a['a'] = np.arange(10)
>>> a['b'] = np.arange(10,20)
>>> a['c'] = np.arange(20,30)

>>> a
array([(0.0, 10.0, 20.0), 
       (1.0, 11.0, 21.0), 
       (2.0, 12.0, 22.0),
       (3.0, 13.0, 23.0), 
       (4.0, 14.0, 24.0), 
       (5.0, 15.0, 25.0),
       (6.0, 16.0, 26.0), 
       (7.0, 17.0, 27.0), 
       (8.0, 18.0, 28.0),
       (9.0, 19.0, 29.0)], 
  dtype=[('a', '<f4'), ('b', '<f4'), ('c', '<f4')])

>>> a['a'][2:6]
array([ 2.,  3.,  4.,  5.], dtype=float32)

>>> a[4:8]
array([(4.0, 14.0, 24.0), 
       (5.0, 15.0, 25.0), 
       (6.0, 16.0, 26.0),
       (7.0, 17.0, 27.0)], 
  dtype=[('a', '<f4'), ('b', '<f4'), ('c', '<f4')])

【讨论】:

    【解决方案2】:

    重复使用这样的模式:

        if shape in self.measurements:
            shape_dict = self.measurements[shape]
        else:
            shape_dict = {}
            self.measurements[shape] = shape_dict
    

    建议您可以使用collections.defaultdict 获利。

    当我用一些measurements 填充你的all_measurements 对象时(使用我自己的简单类),

    A = all_measurements()
    A.add_measurement(measurement('round',10,20.0,'test0'))
    A.add_measurement(measurement('square',10,30.0,'test1'))
    A.add_measurement(measurement('round',1,20.0,'test2'))
    print(A.measurements)
    

    我得到了一个看起来像这样的字典:

    {'square': {10: {30.0: {'test1': measurement: square,10,30.0,test1}}},
     'round': {1: {20.0: {'test2': measurement: round,1,20.0,test2}}, 
               10: {20.0: {'test0': measurement: round,10,20.0,test0}}}}
    

    我在这里看不到任何看起来像 3d 数组的东西。

    我想如果有一套标准的形状、尺寸和压力,例如

    shapes = ['round', 'square', 'flat']
    sizes = [1,3,10,20]
    pressures = [10.0, 20.0, 30.0]
    

    你可以构造一个 3d 数组,例如

    np.empty((3,4,3))
    

    以及将标签映射到索引的字典或元组列表,例如

    sizemap={1:0, 3:1, 10:2, 20:3}
    sizelist=[(1,0),(3,1)...]
    

    但是这个数组的值是什么? measurement 对象? ndarrays 类型的 object 是可能的,但通常没有嵌套列表或字典的优势。


    我测试了你的get_measurements。按照现在的结构,你必须选择形状,然后在其中选择尺寸等。它不能返回具有特定尺寸值的所有形状。

    这个方法,让我使用索引,包括切片,语法来传递参数给你的get_measurements

    def __getitem__(self, key):
        print(key)
        key = list(key)  # comes in a tuple
        for i,k in enumerate(key):
            if isinstance(k, slice):
                # code to interpret a slice goes here
                key[i] = None # fall back, do nothing
        return self.get_measurements(*key)
    
    pprint(A['round',10])
    pprint(A[:,10])
    pprint(A['round':'square', 10:30:10])
    

    生产

    ('round', 10)
    {20.0: {'test0': measurement: round,10,20.0,test0}}
    
    (slice(None, None, None), 10)
    {'round': ...}
    
    (slice('round', 'square', None), slice(10, 30, 10))
    {'round': ...}
    

    你必须决定喜欢什么对象

    slice('round','square', None)
    slice(10, 30, 10)
    

    在你的属性的上下文中表示

    【讨论】:

    • 这个想法是快速获得“统计”数据:即获得所有方形的测量值。或所有具有 60 条的测量值。或4mm的尺寸。或 2 个参数的组合。 (比如所有测量都是正方形的,并且是在 100 bar 压力下完成的)。
    • 这听起来更像是数据库问题而不是数组问题。数组适用于这些参数的每个可能组合都有一个值的情况(None 的可能性)。
    • 我概述了如何将索引和切片添加到您的类中。
    猜你喜欢
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多