Error:setting an array element with a sequence - python-3.x

if triangles is None:
tridata = mesh['face'].data['vertex_indices']
print(tridata)
print(type(tridata))
print(tridata.dtype)
triangles = plyfile.make2d(tridata)
there have a error :setting an array element with a sequence.
I check the type of tridata:
[array([ 0, 5196, 10100], dtype=int32)
array([ 0, 2850, 10103], dtype=int32)
array([ 0, 3112, 10102], dtype=int32) ...
array([ 2849, 10076, 5728], dtype=int32)
array([ 2849, 10099, 8465], dtype=int32)
array([ 2849, 10098, 8602], dtype=int32)]
<class 'numpy.ndarray'>
object
ValueError:Error:setting an array element with a sequence.
I don't know where is wrong?
There is the code of function "make2d" :
def make2d(array, cols=None, dtype=None):
'''
Make a 2D array from an array of arrays. The `cols' and `dtype'
arguments can be omitted if the array is not empty.
'''
if (cols is None or dtype is None) and not len(array):
raise RuntimeError("cols and dtype must be specified for empty "
"array")
if cols is None:
cols = len(array[0])
if dtype is None:
dtype = array[0].dtype
return _np.fromiter(array, [('_', dtype, (cols,))],
count=len(array))['_']

Where's this code from? The use of a compound dtype in fromiter is tricky.
In [102]: dt1=np.dtype([('_',int,(4,))])
In [103]: dt2=np.dtype('i,i,i,i')
In [104]: x = np.arange(12).reshape(3,4)
In [105]: np.fromiter(x, dt1)
....
ValueError: setting an array element with a sequence.
In [106]: np.fromiter(x, dt2)
...
ValueError: setting an array element with a sequence.
If I flatten the array, it works - except values are replicated:
In [107]: np.fromiter(x.ravel(), dt1)
Out[107]:
array([([ 0, 0, 0, 0],), ([ 1, 1, 1, 1],), ([ 2, 2, 2, 2],),
([ 3, 3, 3, 3],), ([ 4, 4, 4, 4],), ([ 5, 5, 5, 5],),
([ 6, 6, 6, 6],), ([ 7, 7, 7, 7],), ([ 8, 8, 8, 8],),
([ 9, 9, 9, 9],), ([10, 10, 10, 10],), ([11, 11, 11, 11],)],
dtype=[('_', '<i8', (4,))])
Converting the array to a nested list, works:
In [108]: np.fromiter(x.tolist(), dt1)
Out[108]:
array([([ 0, 1, 2, 3],), ([ 4, 5, 6, 7],), ([ 8, 9, 10, 11],)],
dtype=[('_', '<i8', (4,))])
In [109]: np.fromiter(x.tolist(), dt2)
....
ValueError: setting an array element with a sequence.
But if I make it a list of tuples, I can create this structured array. List of tuples is the normal way of filling a structured array.
In [110]: np.fromiter([tuple(i) for i in x.tolist()], dt2)
Out[110]:
array([(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
But with an object dtype array, none of these tricks work:
In [111]: a
Out[111]:
array([array([0, 1, 2, 3]), array([5, 6, 7, 8]), array([10, 11, 12, 13])],
dtype=object)
I can make an array with dt1 using assignment to an initialized array:
In [123]: b = np.zeros((3,), dt1)
In [124]: b
Out[124]:
array([([0, 0, 0, 0],), ([0, 0, 0, 0],), ([0, 0, 0, 0],)],
dtype=[('_', '<i8', (4,))])
In [125]: b['_']=x
In [126]: b
Out[126]:
array([([ 0, 1, 2, 3],), ([ 4, 5, 6, 7],), ([ 8, 9, 10, 11],)],
dtype=[('_', '<i8', (4,))])
I can also iteratively fill it from the array of arrays:
In [128]: for i in range(3):
...: b['_'][i]=a[i]
...:
In [129]: b
Out[129]:
array([([ 0, 1, 2, 3],), ([ 5, 6, 7, 8],), ([10, 11, 12, 13],)],
dtype=[('_', '<i8', (4,))])

Related

PyTorch: How to insert before a certain element

Currently I have a 2D tensor, for each row, I want to insert a new element e before the first index of a specified value v. Additional information: cannot guarantee each row could have a such value. If there isn't, just append the element
Example: Supporse e is 0, v is 10, Given a tensor
[[9, 6, 5, 4, 10],
[8, 7, 3, 5, 5],
[4, 9, 10, 10, 10]]
I want to get
[[9, 6, 5, 4, 0, 10],
[8, 7, 3, 5, 5, 0],
[4, 9, 0, 10, 10, 10]]
Are there some Torch-style ways to do this? The worst case I can treat this as a trivial Python problem but I think the corresponding solution is a little time-consuming.
I haven't yet found a full PyTorch solution. I'll keep looking, but here is somewhere to start:
>>> v, e = 10, 0
>>> v, e = torch.tensor([v]), torch.tensor([e])
>>> x = torch.tensor([[ 9, 6, 5, 4, 10],
[ 8, 7, 3, 5, 5],
[ 4, 9, 10, 10, 10],
[10, 9, 7, 10, 2]])
To deal with the edge case where v is not found in one of the rows you can add a temporary column to x. This will ensure every row has a value v in it. We will use x_ as a helper tensor:
>>> x_ = torch.cat([x, v.repeat(x.size(0))[:, None]], axis=1)
tensor([[ 9, 6, 5, 4, 10, 10],
[ 8, 7, 3, 5, 5, 10],
[ 4, 9, 10, 10, 10, 10],
[10, 9, 7, 10, 2, 10]])
Find the indices of the first value v on each row:
>>> bp = (x_ == v).int().argmax(axis=1)
tensor([4, 5, 2, 0])
Finally, the easiest way to insert values at different positions in each row is with a list comprehension:
>>> torch.stack([torch.cat([xi[:bpi], e, xi[bpi:]]) for xi, bpi in zip(x, bp)])
tensor([[ 9, 6, 5, 4, 0, 10],
[ 8, 7, 3, 5, 5, 0],
[ 4, 9, 0, 10, 10, 10],
[ 0, 10, 9, 7, 10, 2]])
Edit - If v cannot occur in the first position, then no need for x_:
>>> x
tensor([[ 9, 6, 5, 4, 10],
[ 8, 7, 3, 5, 5],
[ 4, 9, 10, 10, 10]])
>>> bp = (x == v).int().argmax(axis=1) - 1
>>> torch.stack([torch.cat([xi[:bpi], e, xi[bpi:]]) for xi, bpi in zip(x, bp)])
tensor([[ 9, 6, 5, 0, 4, 10],
[ 8, 7, 3, 5, 0, 5],
[ 4, 0, 9, 10, 10, 10]])

Simplify numpy expression [duplicate]

This question already has answers here:
Access n-th dimension in python [duplicate]
(5 answers)
Closed 2 years ago.
How can I simplify this:
import numpy as np
ex = np.arange(27).reshape(3, 3, 3)
def get_plane(axe, index):
return ex.swapaxes(axe, 0)[index] # is there a better way ?
I cannot find a numpy function to get a plane in a higher dimensional array, is there one?
EDIT
The ex.take(index, axis=axe) method is great, but it copies the array instead of giving a view, what I originally wanted.
So what is the shortest way to index (without copying) a n-th dimensional array to get a 2d slice of it, with index and axis?
Inspired by this answer, you can do something like this:
def get_plane(axe, index):
slices = [slice(None)]*len(ex.shape)
slices[axe]=index
return ex[tuple(slices)]
get_plane(1,1)
output:
array([[ 3, 4, 5],
[12, 13, 14],
[21, 22, 23]])
What do you mean by a 'plane'?
In [16]: ex = np.arange(27).reshape(3, 3, 3)
Names like plane, row, and column, are arbitrary conventions, not formally defined in numpy. The default display of this array looks like 3 'planes' or 'blocks', each with rows and columns:
In [17]: ex
Out[17]:
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
Standard indexing lets us view any 2d block, in any dimension:
In [18]: ex[0]
Out[18]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [19]: ex[0,:,:]
Out[19]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [20]: ex[:,0,:]
Out[20]:
array([[ 0, 1, 2],
[ 9, 10, 11],
[18, 19, 20]])
In [21]: ex[:,:,0]
Out[21]:
array([[ 0, 3, 6],
[ 9, 12, 15],
[18, 21, 24]])
There are ways of saying I want block 0 in dimension 1 etc, but first make sure you understand this indexing. This is the core numpy functionality.
In [23]: np.take(ex, 0, 1)
Out[23]:
array([[ 0, 1, 2],
[ 9, 10, 11],
[18, 19, 20]])
In [24]: idx = (slice(None), 0, slice(None)) # also np.s_[:,0,:]
In [25]: ex[idx]
Out[25]:
array([[ 0, 1, 2],
[ 9, 10, 11],
[18, 19, 20]])
And yes you can swap axes (or transpose), it that suits your needs.

Array conforming shape of a given variable

I need to do some calculations with a NetCDF file.
So I have two variables with following dimensions and sizes:
A [time | 1] x [lev | 12] x [lat | 84] x [lon | 228]
B [lev | 12]
What I need is to produce a new array, C, that is shaped as (1,12,84,228) where B contents are propagated to all dimensions of A.
Usually, this is easily done in NCL with the conform function. I am not sure what is the equivalent of this in Python.
Thank you.
The numpy.broadcast_to function can do something like this, although in this case it does require B to have a couple of extra trailing size 1 dimension added to it to satisfy the numpy broadcasting rules
>>> import numpy
>>> B = numpy.arange(12).reshape(12, 1, 1)
>>> B
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> B = B.reshape(12, 1, 1)
>>> B.shape
(12, 1, 1)
>>> C = numpy.broadcast_to(b, (1, 12, 84, 228))
>>> C.shape
(1, 12, 84, 228)
>>> C[0, :, 0, 0]
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> C[-1, :, -1, -1]
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])

Filled with numpy.zero but getting nan instead

I have a Class that contains various methods with include the following:
def _doc_mean(self, doc):
doc_vector_values = []
for w in doc:
#print(w)
if w.lower().strip() in self._E:
Q = np.zeros((1, 200), dtype=np.float64) #this is a zero array for when a word doesnt have a vector representation in our pretrained embeddings
doc_vector_values.append(self._E.get(w, Q))
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=RuntimeWarning)
return np.mean(np.array(doc_vector_values, dtype=np.float64), axis=0)
def fit(self, X, y=None):
return self
def transform(self, X):
return np.array([self._doc_mean(doc) for doc in X])
def fit_transform(self, X, y=None):
return self.fit(X).transform(X)
in _doc_mean, i compare w with the keys in a dictionary E_, if there is a match, then load the value of the key-value pair which contains a 1*200 vector into a list, if there is no match, then load numpy.zeros((1,200)) into a list. This list is now converted to an array and the mean calculated.
When i instantiate the class and fit-transform my 'doc' data
mc = MeanClass()
X_ = mc.fit_transform(doc)
X_ is of dtype "object" and the places where there was a mismatch was replaced with nan instead of numpy.zero.
This leads to multiple other problems in my code that i cant fix. What am i doing wrong?
EDIT:
The E_ dictionary looks like this :
{'hello': array([ 5.84850e-02, 6.20640e-02, ..... -2.08990e-02])
'good': array([ -4.80050e-02, 2.80610e-02, ..... -5.04991e-02])
while doc looks like this :
['hello', 'bye', 'good']
['good', 'bye', 'night']
Since you haven't given a [mcve], I'll create something simple:
In [125]: E_ = {'foo':np.arange(5), 'bar':np.arange(1,6), 'baz':np.arange(5,10)}
In [126]: doc = ['foo','bar','sub','baz','foo']
Now do the dictionary lookup:
In [127]: alist = []
In [128]: for w in doc:
...: alist.append(E_.get(w,np.zeros((1,5),int)))
...:
In [129]: alist
Out[129]:
[array([0, 1, 2, 3, 4]),
array([1, 2, 3, 4, 5]),
array([[0, 0, 0, 0, 0]]),
array([5, 6, 7, 8, 9]),
array([0, 1, 2, 3, 4])]
In [130]: np.array(alist)
Out[130]:
array([array([0, 1, 2, 3, 4]), array([1, 2, 3, 4, 5]),
array([[0, 0, 0, 0, 0]]), array([5, 6, 7, 8, 9]),
array([0, 1, 2, 3, 4])], dtype=object)
The arrays in E_ are all shape (5,). The 'fill' array is (1,5). Due to the mismatch in shapes, the Out[130] array is 1d object.
I think you are trying to avoid the 'fill' case, but you test w.lower().strip() in self._E, and then use w in the get. So you might get the Q value sometimes. I got it with the 'sub' string.
If instead I make the 'fill' be (5,):
In [131]: alist = []
In [132]: for w in doc:
...: alist.append(E_.get(w,np.zeros((5,),int)))
...:
In [133]: alist
Out[133]:
[array([0, 1, 2, 3, 4]),
array([1, 2, 3, 4, 5]),
array([0, 0, 0, 0, 0]),
array([5, 6, 7, 8, 9]),
array([0, 1, 2, 3, 4])]
In [134]: np.array(alist)
Out[134]:
array([[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[0, 0, 0, 0, 0],
[5, 6, 7, 8, 9],
[0, 1, 2, 3, 4]])
The result is a (n,5) numeric array.
I can take two different means. One is the mean across all words, with a value for each 'attribute'. The other is the mean for each word, which I could just as well have gotten by taking the mean in E_.
In [135]: np.mean(_, axis=0)
Out[135]: array([1.2, 2. , 2.8, 3.6, 4.4])
In [137]: np.mean(__, axis=1)
Out[137]: array([2., 3., 0., 7., 2.]) # mean for each 'word'
mean of the object array in Out[130]:
In [138]: np.mean(_130, axis=0)
Out[138]: array([[1, 2, 2, 3, 4]])
The result is (1,5) and looks like Out[135] truncated, but I'd have to dig a bit further to be sure.
Hopefully this gives you an idea of what to watch out for. And an idea of the kind of 'minimal reproducable concrete example' that we find most useful.

Sampling from a 2d numpy array

I was wondering if there was a reasonably efficient way of sampling from a 2d numpy array. If I have a generic array:
dims = (4,4)
test_array = np.arange(np.prod(dims)).reshape(*dims)
test_array
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
Then I'd like to randomly set, say, two elements from it to a specific value (let's say 100). I've tried creating an indexing array and then applying that:
sample_from = np.random.randint(low=0, high=5, size=(2,2))
sample_from
array([[0, 2],
[1, 1]])
But if I try using this to index, it gives me a slightly unexpected answer:
test_array[sample_from]
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[ 4, 5, 6, 7]]])
What I would have expected (and the kind of result I'd like) is if I'd just entered the indexing array directly:
test_array[[0,2],[1,1]] = 100
test_array
giving:
array([[ 0, 100, 2, 3],
[ 4, 5, 6, 7],
[ 8, 100, 10, 11],
[ 12, 13, 14, 15]])
Any help gratefully received.
You could use np.random.choice + np.unravel_index to assign directly to your array.
test_array[
np.unravel_index(np.random.choice(np.prod(dims), 2, replace=False), dims)
] = 100

Resources