2013-03-03 4 views
20

я могу видеть несколько колонок (fields) сразу в numpy структурированном массиве путем индексации со списком имен полей, напримерКак вернуть вид нескольких столбцов в NumPy структурированного массива

import numpy as np 

a = np.array([(1.5, 2.5, (1.0,2.0)), (3.,4.,(4.,5.)), (1.,3.,(2.,6.))], 
     dtype=[('x',float), ('y',float), ('value',float,(2,2))]) 

print a[['x','y']] 
#[(1.5, 2.5) (3.0, 4.0) (1.0, 3.0)] 

print a[['x','y']].dtype 
#[('x', '<f4') ('y', '<f4')]) 

Но проблема заключается в том, что это, кажется, копию, а не с точки зрения:

b = a[['x','y']] 
b[0] = (9.,9.) 

print b 
#[(9.0, 9.0) (3.0, 4.0) (1.0, 3.0)] 

print a[['x','y']] 
#[(1.5, 2.5) (3.0, 4.0) (1.0, 3.0)] 

Если я выбрать только один столбец, это мнение:

c = x['y'] 
c[0] = 99. 

print c 
#[ 99. 4. 3. ] 

print a['y'] 
#[ 99. 4. 3. ] 

Есть ли способ получить представление для более чем одного столбца одновременно?

У меня есть два метода обхода, один - просто пройти через столбцы, другой - создать иерархический dtype, так что один столбец фактически возвращает структурированный массив с двумя (или более) полями, которые я хочу. К сожалению, zip также возвращает копию, так что я не могу сделать:

x = a['x']; y = a['y'] 
z = zip(x,y) 
z[0] = (9.,9.) 

ответ

29

Вы можете создать объект DTYPE содержит только те поля, которые вы хотите, и использовать numpy.ndarray(), чтобы создать представление исходного массива:

import numpy as np 
strc = np.zeros(3, dtype=[('x', int), ('y', float), ('z', int), ('t', "i8")]) 

def fields_view(arr, fields): 
    dtype2 = np.dtype({name:arr.dtype.fields[name] for name in fields}) 
    return np.ndarray(arr.shape, dtype2, arr, 0, arr.strides) 

v1 = fields_view(strc, ["x", "z"]) 
v1[0] = 10, 100 

v2 = fields_view(strc, ["y", "z"]) 
v2[1:] = [(3.14, 7)] 

v3 = fields_view(strc, ["x", "t"]) 

v3[1:] = [(1000, 2**16)] 

print(strc) 

здесь выход:

[(10, 0.0, 100, 0L) (1000, 3.14, 7, 65536L) (1000, 3.14, 7, 65536L)] 
+2

Ooh, это хорошо, работает Непоследовательных (или неравномерно разнесены) поля. – askewchan

+0

Это замечательно! Как у него есть только 1 upvote? – AndyJost

+0

Новый ответ на старый вопрос @andy не обращает на это особого внимания: P – askewchan

4

Я не думаю, что есть простой способ добиться того, что вы хотите. В общем, вы не можете взять произвольный вид в массив. Попробуйте выполнить следующее:

>>> a 
array([(1.5, 2.5, [[1.0, 2.0], [1.0, 2.0]]), 
     (3.0, 4.0, [[4.0, 5.0], [4.0, 5.0]]), 
     (1.0, 3.0, [[2.0, 6.0], [2.0, 6.0]])], 
     dtype=[('x', '<f8'), ('y', '<f8'), ('value', '<f8', (2, 2))]) 
>>> a.view(float) 
array([ 1.5, 2.5, 1. , 2. , 1. , 2. , 3. , 4. , 4. , 5. , 4. , 
     5. , 1. , 3. , 2. , 6. , 2. , 6. ]) 

Поплавковый вид вашего массива записей показывает, как фактические данные хранятся в памяти. Взгляд на эти данные должен быть выражен как комбинация формы, шага и смещения в вышеупомянутые данные. Так что если вы хотите, например, вид 'x' и 'y' только, вы можете сделать следующее:

>>> from numpy.lib.stride_tricks import as_strided 
>>> b = as_strided(a.view(float), shape=a.shape + (2,), 
        strides=a.strides + a.view(float).strides) 
>>> b 
array([[ 1.5, 2.5], 
     [ 3. , 4. ], 
     [ 1. , 3. ]]) 

as_strided делает то же самое, как, возможно, легче понять:

>>> bb = a.view(float).reshape(a.shape + (-1,))[:, :2] 
>>> bb 
array([[ 1.5, 2.5], 
     [ 3. , 4. ], 
     [ 1. , 3. ]]) 

Любой из это вид в a:

>>> b[0,0] =0 
>>> a 
array([(0.0, 2.5, [[0.0, 2.0], [1.0, 2.0]]), 
     (3.0, 4.0, [[4.0, 5.0], [4.0, 5.0]]), 
     (1.0, 3.0, [[2.0, 6.0], [2.0, 6.0]])], 
     dtype=[('x', '<f8'), ('y', '<f8'), ('value', '<f8', (2, 2))]) 
>>> bb[2, 1] = 0 
>>> a 
array([(0.0, 2.5, [[0.0, 2.0], [1.0, 2.0]]), 
     (3.0, 4.0, [[4.0, 5.0], [4.0, 5.0]]), 
     (1.0, 0.0, [[2.0, 6.0], [2.0, 6.0]])], 
     dtype=[('x', '<f8'), ('y', '<f8'), ('value', '<f8', (2, 2))]) 

было бы хорошо, если бы ни это может быть преобразована в запись обр да, но NumPy отказывается сделать это, то причина не быть все, что для меня ясно:

>>> b.view([('x',float), ('y',float)]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: new type not compatible with array. 

Конечно, что работает (вроде) для 'x' и 'y' не будет работать, например, для 'x' и 'value', поэтому в целом ответ: это невозможно.

7

Опираясь на @ Ответ HYRY, вы также можете использовать метод getfield:

def fields_view(array, fields): 
    return array.getfield(numpy.dtype(
     {name: array.dtype.fields[name] for name in fields} 
    )) 
+0

Ницца, как мы это пропустили? Кажется чистым и экономичным, чтобы избежать передачи данных и шагов. ['getfield'] (https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.getfield.html), похоже, не является [новым] (https: //docs.scipy. org/doc/numpy-1.6.0/reference/generated/numpy.ndarray.getfield.html), хотя я никогда не видел его раньше. – askewchan

2

По состоянию на номер 1.13, код, который вы предлагаете , будет вернуть представление. Смотрите «NumPy 1.12.0 релиз Notes-> Будущие Изменения-> манипуляция Multiple поля структурированных массивов» на этой странице:

https://docs.scipy.org/doc/numpy-dev/release.html

Смежные вопросы