7

Very simple question: I have a structured array with multiple columns and I'd like to fill only some of them (but more than one) with another preexisting array.

This is what I'm trying:

strc = np.zeros(4, dtype=[('x', int), ('y', int), ('z', int)])
x = np.array([2, 3])
strc[['x', 'y']][0] = x

This gives me this future warning:

main:1: FutureWarning: Numpy has detected that you (may be) writing to an array returned by numpy.diagonal or by selecting multiple fields in a record array. This code will likely break in a future numpy release -- see numpy.diagonal or arrays.indexing reference docs for details. The quick fix is to make an explicit copy (e.g., do arr.diagonal().copy() or arr[['f0','f1']].copy()).

But even though this is a warning, the structured array doesn't get filled. So far I'm iterating over both arrays and it works but I guess that's highly inefficient. Is there a better way?

Federico Barabas
  • 599
  • 6
  • 20
  • http://stackoverflow.com/questions/3058602/python-numpy-structured-array-recarray-assigning-values-into-slices points out that trying to index several fields produces a copy, not a view. If you are working with more rows than fields, there's nothing wrong with iterating over fields. – hpaulj Feb 17 '14 at 05:59

1 Answers1

12

If all the field have the same dtype, you can create a view:

import numpy as np
strc = np.zeros(4, dtype=[('x', int), ('y', int), ('z', int)])
strc_view = strc.view(int).reshape(len(strc), -1)
x = np.array([2, 3])
strc_view[0, [0, 1]] = x

If you want a common solution that can create columns views of any structured array, you can try:

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

here is the output:

[(10, 0.0, 100, 0L) (1000, 3.14, 7, 65536L) (1000, 3.14, 7, 65536L)]
HYRY
  • 83,863
  • 22
  • 167
  • 176