1

I found a strange situation with my code and the issue is shown in the code bellow

import numpy as np

dt = dict(names = ['n1','n2'], formats = ['a8','int'])
reca = np.recarray((10,), dtype = dt)
reca['n1'] = ['a','b','c','d','e','f','g','e','f','g']
reca['n2'] = range(10)

sreca = reca[::2]
print sreca[0] in reca

sreca[0]['n2'] = 12
print sreca[0] in reca

ireca = reca[[1,3,5,7]]
print ireca[0] in reca

ireca[0]['n2'] = 7
print ireca[0] in reca

The output is:

True
True
True
False

To my understand, either sreca or ireca should keep a reference of reca unless i assign a new value to them directly, but ireca lost its reference after the assignment. I don't know if this is expected or not.

Could any one advice me how to avoid this?

BTW, I found that a small change of the code (reca['n1'] = ['a']*10 for example) will give me all True in this sample, this really make me confused.

guofeng
  • 15
  • 3

2 Answers2

2

Using fancy indexing in a recarray will copy the data to a new array. Instead you could do:

ireca = [reca[i] for i in [1,3,5,7]]

since taking only one entry of the recarray keeps the reference. You can check when a new array has been created using the flags parameter:

  • print(reca[0].flags) shows OWNDATA : False
  • print(reca[[0,1]].flags) shows OWNDATA : True
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
  • So it means that fancy indexing should be avoid in this case and the keyword 'in' is not supposed to be used for checking if a copy is made or not? Then what is the way to create a indexing view of reca rather than a simple list? I still need to call ireca['n1'] frequently afterward. – guofeng Aug 27 '14 at 17:36
  • @guofeng in this approach each item in the list is a view of one part of your recarray... such that no copy is made – Saullo G. P. Castro Aug 27 '14 at 18:07
  • @guofeng did this answer fit to your needs? IF yes I just wanted to remind you can accept the answer... – Saullo G. P. Castro Aug 28 '14 at 10:29
0

You first assigned to ireca the following components:

>>> ireca = reca[[1,3,5,7]]
>>> ireca 
rec.array([('b', 1), ('d', 3), ('f', 5), ('e', 7)], 
      dtype=[('n1', 'S8'), ('n2', '<i8')])

Then you assign to the first component in 'n2' instead of 1, 7 and then you want to see whether it is still in the parent array reca or not and since the second component has changed then it is no longer in reca so you get False result.

>>> ireca[0]['n2']=7
>>> ireca[0]
('b', 7)
>>> ireca
rec.array([('b', 7), ('d', 3), ('f', 5), ('e', 7)], 
      dtype=[('n1', 'S8'), ('n2', '<i8')])

>>> print ireca[0] in reca
False
Dalek
  • 4,168
  • 11
  • 48
  • 100
  • It is interesting that if you replace my 4th line whit reca['n1'] = ['a']*10, you will get True. – guofeng Aug 27 '14 at 16:43