0

I have an array defined as -

import numpy as np
A = np.recarray((3,),dtype=[('x',float), ('y', float), ('z',float)])

Plus another array B which is read from a CSV file as -

>>> print B
[(7.0, 0.0, 7.0) (16.0, 0.0, 1.0)]

When I try to add the elements to array as given below -

for i in range(B.size):
    if(B[i][0] != 0.):
        A.append((0.,B[i][1],B[i][2]))
    if(B[i][1] != 0.):
        A.append((B[i][0],0.,B[i][2]))
    if(B[i][2] != 0.):
        A.append((B[i][0],B[i][1],0.))

I get an error as follows -

File "/usr/lib/python2.7/dist-packages/numpy/core/records.py", line 416, in __getattribute__
    raise AttributeError, "record array has no attribute %s" % attr
    AttributeError: record array has no attribute append

I am not able to understand where does this string attribute (%s) is coming into picture?

Can someone help out please?

UPDATE: I changed the code to np.append(A,(0.,B[i][1],B[i][2])), however I get another error as - TypeError: invalid type promotion

Raj
  • 3,300
  • 8
  • 39
  • 67
  • "%S" is just showing the stacktrace. – spicavigo Oct 12 '12 at 09:50
  • Duplicate of http://stackoverflow.com/questions/9775297/append-a-numpy-array-to-a-numpy-array (and probably others) there is `numpy.append`, but its usually not the best solution. – seberg Oct 12 '12 at 11:03
  • Actually, since these are recarrays, there might be some more details involved when concatenating (`np.lib.recfunctions.stack_arrays` may help in that case), but that should be no problem if the fields are identical. – seberg Oct 12 '12 at 11:15

2 Answers2

1

The error is just saying that recarray does not have any method called append.

I have not really used numpy but one solution could be to convert A into list

A.tolist()

appending records to this list and then doing something like

np.fromiter(x, A.dtype)

to get the new recarray. This, of course, does not look like a good solution.

Perhaps someone more familiar with numpy will be able to pitch in and improve it.

spicavigo
  • 4,116
  • 22
  • 28
1

Appending to a numpy array is a slow operation because new memory has to be allocated and the entire array has to be copied. Doing this for each row of B would be inefficient. Avoid this if you can.

If you know the shape of A and minors(B) (see below) in advance, it is best to make an array which is big enough to accomodate both from the beginning.

There are many was to do what you asking. @seberg's np.lib.recfunctions.stack_arrays idea would make a viable solution as long as the dtypes of A and B are the same.

Here is another possibility, which will work even if B has a different dtype, or is just a ndarray or list of lists.

import itertools
import numpy as np

def minors(arr):
    for row in arr:
        row = list(row)
        for i, elt in enumerate(row):
            if elt != 0:
                for val in row[:i]+[0]+row[i+1:]:
                    yield val

A = np.recarray((3,),dtype=[('x',float), ('y', float), ('z',float)])
B = [(7.0, 0.0, 7.0), (16.0, 0.0, 1.0)]

C = np.fromiter(itertools.chain(A.view(float), minors(B)), dtype = float)
C = C.view(A.dtype)
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • your code gave me an answer like this - `>>> print C [(3.1310608122305046e-307, -3.263691770160412e-42, -3.2646770584641245e-42) (-3.2646770580222135e-42, -1.1666518207782148e-41, -1.086168727138965e-41) (-1.1664766582821353e-41, 3.277940205911456e-260, 8.330460061897614e-259) (0.0, 0.0, 7.0) (7.0, 0.0, 0.0) (0.0, 0.0, 1.0) (16.0, 0.0, 0.0)]`. I think the first 3 entries are garbage? – Raj Oct 12 '12 at 12:40
  • 1
    @RajTendulkar `A` is initialized with garbage, that is correct, maybe you are lookng for `A = np.recarray((0,), ...)`. The `np.lib.recfunctions.stack_array` are a generalization for recarrays that can handle different fields, if fields are guaranteed to be completly the same, normal concatenation works. – seberg Oct 12 '12 at 13:52