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

3
  • "%S" is just showing the stacktrace. Commented Oct 12, 2012 at 9:50
  • Duplicate of stackoverflow.com/questions/9775297/… (and probably others) there is numpy.append, but its usually not the best solution. Commented Oct 12, 2012 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. Commented Oct 12, 2012 at 11:15

2 Answers 2

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)
Sign up to request clarification or add additional context in comments.

2 Comments

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?
@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.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.