python - numpy中的命名元组

标签 python oop numpy namedtuple

我真的很喜欢namedtuple集合的功能。具体来说,我喜欢它对于二维空间中的点有多大用处。

In : from collections import namedtuple

In : Point = namedtuple('Point', ['x', 'y'])

In : p = Point(1,2)

In : p.x
Out: 1

In : p.y
Out: 2

我认为这比引用列表的第一和第二个条目要清晰得多。我想知道是否有一种方法可以使Point也是一个numpy数组。例如
 In: p1 = Point(1,2)
 In: p2 = Point(3,4)
 In: (p1+p2).x 
 Out: 4

还有numpy的类似不错的功能。换句话说,我想让Point成为numpy的子类?我可以这样做吗?如何?

最佳答案

point_type这样的结构化数组未定义涉及多个字段的数学运算。

来自https://stackoverflow.com/a/33455682/901925的样本

In [470]: point_type = [('x', float), ('y', float)]
In [471]: points = np.array([(1,2), (3,4), (5,6)], dtype=point_type)
In [472]: points
Out[472]: 
array([(1.0, 2.0), (3.0, 4.0), (5.0, 6.0)], 
      dtype=[('x', '<f8'), ('y', '<f8')])
In [473]: points[0]+points[1]
...
TypeError: unsupported operand type(s) for +: 'numpy.void' and 'numpy.void'

相反,我可以创建一个2d数组,然后将其查看为point_type-数据缓冲区布局将相同:
In [479]: points = np.array([(1,2), (3,4), (5,6)],float)
In [480]: points
Out[480]: 
array([[ 1.,  2.],
       [ 3.,  4.],
       [ 5.,  6.]])
In [481]: points.view(point_type)
Out[481]: 
array([[(1.0, 2.0)],
       [(3.0, 4.0)],
       [(5.0, 6.0)]], 
      dtype=[('x', '<f8'), ('y', '<f8')])
In [482]: points.view(point_type).view(np.recarray).x
Out[482]: 
array([[ 1.],
       [ 3.],
       [ 5.]])

我可以跨行进行数学运算,并继续以点的形式查看结果:
In [483]: (points[0]+points[1]).view(point_type).view(np.recarray)
Out[483]: 
rec.array([(4.0, 6.0)], 
      dtype=[('x', '<f8'), ('y', '<f8')])
In [484]: _.x
Out[484]: array([ 4.])
In [485]: points.sum(0).view(point_type)
Out[485]: 
array([(9.0, 12.0)], 
      dtype=[('x', '<f8'), ('y', '<f8')])

或者,我可以从point_type开始,然后将其视为2d进行数学运算,然后再进行查看
pdt1=np.dtype((float, (2,)))
In [502]: points
Out[502]: 
array([(1.0, 2.0), (3.0, 4.0), (5.0, 6.0)], 
      dtype=[('x', '<f8'), ('y', '<f8')])
In [503]: points.view(pdt1)
Out[503]: 
array([[ 1.,  2.],
       [ 3.,  4.],
       [ 5.,  6.]])
In [504]: points.view(pdt1).sum(0).view(point_type)
Out[504]: 
array([(9.0, 12.0)], 
      dtype=[('x', '<f8'), ('y', '<f8')])

因此,可以将数组作为2d和recarray进行查看和操作。要漂亮或有用,可能需要将其埋入用户定义的类中。

来自recarray类的婴儿床想法的另一种选择。它的核心只是带有专用__getattribute__(和setattribute)方法的结构化数组。该方法首先尝试使用普通的数组方法和属性(例如x.shapex.sum)。然后,它尝试在定义的字段名称中优化attr
def __getattribute__(self, attr):
    try:
        return object.__getattribute__(self, attr)
    except AttributeError: # attr must be a fieldname
        pass
    fielddict = ndarray.__getattribute__(self, 'dtype').fields
    try:
        res = fielddict[attr][:2]
    except (TypeError, KeyError):
        raise AttributeError("record array has no attribute %s" % attr)
    return self.getfield(*res)
    ...
points.view(np.recarray).x变为points.getfield(*points.dtype.fields['x'])

另一种方法是从namedtuple(/usr/lib/python3.4/collections/__init__.py)借用,并定义xy属性,这将为2d数组的[:,0][:,1]列建立索引。
将这些属性添加到np.matrix的子类中可能是最简单的,让该类确保大多数数学结果为2d。

关于python - numpy中的命名元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33428163/

相关文章:

python - 在 python 3.5 上键入提示语法错误

python - 通过 Python 客户端进行 Hive 查询

python - multiprocessing.Connect 线程安全吗?

java - 无法对 ArrayList 执行操作

Python像matlab一样删除带有bool索引的矩阵行

Python:距离直线最近的点

language-agnostic - 构造函数:完整的还是最小的?

C++ 错误 : request for member 'push_back' in 'v'

Python:获取对字符串数组进行排序以匹配另一个字符串数组的索引

python - 将整数数组编码为唯一的 int