Numpy数组作为具有非唯一属性的向量

时间:2013-03-03 11:38:41

标签: python multidimensional-array numpy

我有一组数据,我想用numpy来对待。可以将数据看作空间中的一组点,并使用我想要作为对象处理的附加属性变量。取决于一组数据,矢量可以是长度1,2或3,但是对于给定数据集中的所有点是相同的长度。属性对象是一个自定义类,对于任何两个给定点可以是相同的。

因此,请将此数据视为随机示例(C和H表示包含碳或氢的原子属性的对象...或仅仅是一些随机对象)。这些不会通过文件读入,而是由算法创建。这里C对象可以是相同的,也可以是不同的(例如同位素)。

Example 3D data set (just abstract representation)
C 1 2 3
C 3 4 5
H 1 1 4

我希望有一个包含所有原子位置的numpy数组,这样我就可以执行像矢量操作这样的numpy操作,例如翻译函数def translate(data,vec):return data + vec。我还想并行处理属性对象。一种选择是两个都有两个单独的数组,但是如果我删除一个元素,我也必须显式删除属性数组值。这可能很难处理。

我考虑使用numpy.recarray

x = np.array([(1.0,2,3, "C"), (3.0,2,3, "H")], dtype=[('x', "float64" ),('y',"float6

4“),('z',”float64“),('type',object)])

但是这个数组的shape似乎是(2,),这意味着每个记录都是独立处理的。此外,我似乎无法理解如何使用此类型进行矢量操作:

def translate(data,vec):return data + vec
translate(x,np.array([1,2,3]))
...
TypeError: unsupported operand type(s) for +: 'numpy.ndarray' and 'numpy.ndarray'

numpy.recarray我应该使用什么?有没有更好的方法以更简单的方式处理这个问题,以便我有一个单独的点数字矩阵与一个并行的object数组,如果一个元素被删除(np.delete),它们会被链接?我还简要地考虑过编写一个扩展ndarray的数组对象,但我觉得这可能是不必要的,也可能是灾难性的。

任何想法或建议都会非常有用。

3 个答案:

答案 0 :(得分:2)

如果你将元组(name, type, shape)作为字段的dtype传递,则重新排列的字段可以是ndarray:

In [9]:

import numpy as np

x = np.array([((1.0,2,3), "C"), ((3.0,2,3), "H")], dtype=[('xyz', "float64", (3,)), ('type', object)])

In [11]:

np.delete(x, 0)

Out[11]:

array([([3.0, 2.0, 3.0], 'H')], 
      dtype=[('xyz', '<f8', (3,)), ('type', 'O')])

In [12]:

x["xyz"]

Out[12]:

array([[ 1.,  2.,  3.],
       [ 3.,  2.,  3.]])

In [14]:

x["xyz"] + (10, 20, 30)

Out[14]:

array([[ 11.,  22.,  33.],
       [ 13.,  22.,  33.]])

对于您的翻译功能:

def translate(data,vec):
    tmp = data.copy()
    tmp["xyz"] += vect
    return tmp

如果您想要更灵活的功能,可以考虑使用Pandas.DataFrame

答案 1 :(得分:1)

如果您正在处理原子集合,可以考虑使用Atoms class中的Atomic Simulation Environment (ASE)。它存储原子类型,位置,并具有类似列表的方法来操纵它们。

答案 2 :(得分:0)

一种快速而又脏的方法是将最后一列(或实际上任何一列)设置为标签字典的数字查找:

>>> import numpy
>>> labels = ['H', 'C', 'O']
>>> labels_refs = dict(zip(labels, numpy.arange(len(labels), dtype='float64')))
>>> reverse_labels_refs = dict(zip(numpy.arange(len(labels), dtype='float64'), labels))
>>> x = numpy.array([
...     [1.0,2,3, labels_refs['C']], 
...     [3.0,2,3, labels_refs['H']],
...     [2.0,2,3, labels_refs['C']]])
>>> x
array([[ 1.,  2.,  3.,  1.],
       [ 3.,  2.,  3.,  0.],
       [ 2.,  2.,  3.,  1.]])
>>> extract_refs = numpy.vectorize(
...         lambda label_ref: reverse_labels_refs[label_ref])
>>> labels = extract_refs(x[:, -1]) # Turn the last column back into labels
>>> labels
array(['C', 'H', 'C'], 
      dtype='|S8')

您还可以按标签查找行(例如):

>>> x[numpy.where(x[:,-1] == labels_refs['C']), :-1]
array([[[ 1.,  2.,  3.],
        [ 2.,  2.,  3.]]])