0

Say I have an image of 2x2 pixels named image_array, each pixel color is identified by a tuple of 3 entries (RGB), so the shape of image_array is 2x2x3.

I want to create an np.array c which has the shape 2x2x1 and which last coordinate is an empty set.

I tried this:

import numpy as np
image = (((1,2,3), (1,0,0)), ((1,1,1), (2,1,2)))
image_array = np.array(image)

c = np.empty(image_array.shape[:2], dtype=set)
c.fill(set())
c[0][1].add(124)
print(c)

I get:

[[{124} {124}]
 [{124} {124}]]

And instead I would like the return:

[[{} {124}]
 [{} {}]]

Any idea ?

dallonsi
  • 1,299
  • 1
  • 8
  • 29

4 Answers4

1

whenever you do fill(set()), this will fill the array with exactly same set, as they refer to the same set. To fix this, just make a set if there isnt one everytime you need to add to the set

c = np.empty(image_array.shape[:2], dtype=set)
if not c[0][1]:
    c[0,1] = set([124])
else:
    c[0,1].add(124)
print (c)

# [[None {124}]
#  [None None]]
Abhishek Patel
  • 587
  • 2
  • 8
  • 25
1

Try this:

import numpy as np

x = np.empty((2, 2), dtype=np.object)
x[0, 0] = set(1, 2, 3)

print(x)
[[{1, 2, 3} None]
 [None None]]

For non-number types in numpy you should use np.object.

scrutari
  • 1,378
  • 2
  • 17
  • 33
  • i think he wants his array to have sets of integers for some reason, though – Abhishek Patel Jun 26 '19 at 15:36
  • ok thanks, the problem came from `c[0][1]`. If I replace it by `c[0,1]` it works. Thanks – dallonsi Jun 26 '19 at 15:36
  • Using `empty` when you intend to only set one element usually isn't a good idea. But with `object` dtype, `empty` fills with `None`. As part of your answer you should show the resulting `x`. – hpaulj Jun 26 '19 at 15:36
1

The object array has to be filled with separate set() objects. That means creating them individually, as I do with a list comprehension:

In [279]: arr = np.array([set() for _ in range(4)]).reshape(2,2)                                     
In [280]: arr                                                                                        
Out[280]: 
array([[set(), set()],
       [set(), set()]], dtype=object)

That construction should highlight that fact that this array is closely related to a list, or list of lists.

Now we can do a set operation on one of those elements:

In [281]: arr[0,1].add(124)     # more idiomatic than arr[0][1]                                                                          
In [282]: arr                                                                                        
Out[282]: 
array([[set(), {124}],
       [set(), set()]], dtype=object)

Note that we cannot operate on more than one set at a time. The object array offers few advantages compared to a list.

This is a 2d array; the sets don't form a dimension. Contrast that with

In [283]: image = (((1,2,3), (1,0,0)), ((1,1,1), (2,1,2))) 
     ...: image_array = np.array(image) 
     ...:                                                                                            
In [284]: image_array                                                                                
Out[284]: 
array([[[1, 2, 3],
        [1, 0, 0]],

       [[1, 1, 1],
        [2, 1, 2]]])

While it started with tuples, it made a 3d array of integers.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
-2

Try changing your line c[0][1].add to this.

c[0][1] = 124
print(c)
Antisune
  • 1
  • 1