If I declare an array "v" whose shape is (3,100) when I want to change its values column by column making use a "for" python changes the dimension of "v[:,i]" for (3,) this is annoying and I can't make the change because at the left member it has a (3,) array and in the right, it has an (3,1) array.
I would like to know, why does this happen? and which are my options to cope with this?
Thanks.
v = np.ones( (3, 100) );
for i in range( 0 , 100 ):
v[:,i] = np.array([[1],
[2],
[3]])
ValueError: could not broadcast input array from shape (3,1) into shape (3)
In [379]: M = np.arange(12).reshape(3,4)
Indexing with a scalar reduced the dimension by one. That's a basic rule of indexing - in numpy and python.
In [380]: M[0,:]
Out[380]: array([0, 1, 2, 3])
In [381]: M[:,0]
Out[381]: array([0, 4, 8])
Same for a list:
In [383]: M.tolist()
Out[383]: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
In [384]: M.tolist()[0]
Out[384]: [0, 1, 2, 3]
Index with a list/array or slice, does preserve the dimension:
In [385]: M[:,[0]]
Out[385]:
array([[0],
[4],
[8]])
So assigning a (3,) to the (3,) slot is fine:
In [386]: M[:,0] = [10,20,30]
Assigning a (3,1) to that slot produces an error:
In [387]: M[:,0] = [[10],[20],[30]]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-387-1bbfa6dfa93c> in <module>
----> 1 M[:,0] = [[10],[20],[30]]
ValueError: setting an array element with a sequence.
In [388]: M[:,0] = np.array([[10],[20],[30]]) # or with an array
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-388-6e511ffdc44e> in <module>
----> 1 M[:,0] = np.array([[10],[20],[30]])
ValueError: could not broadcast input array from shape (3,1) into shape (3)
By broadcasting (3,) can go into (1,3), but not (3,1) into (3,). One solution is to flatten the RHS:
In [389]: M[:,0] = np.array([[10],[20],[30]]).ravel()
Assigning to a (3,1) slot also works:
In [390]: M[:,[0]] = np.array([[10],[20],[30]])
In [391]: M[:,0:1] = np.array([[10],[20],[30]])
We could also transpose the (3,1) to (1,3). Or assign to M[:,0][:,None] or M[:,0,None] (both of which create a (3,1)).
What I think you are asking is: how to set them column wise.
v = np.ones( (3,100) )
for i in range( 0 , 100 ):
v[:,i] = np.array([1,
3,
2])
The change is to remove extra brackets in your assignment.
If you are trying to do something else, you can try doing it for rows, and flip array sideways:
v = np.ones((100,3))
for i in range(0,100):
v[i] = np.array([1,3,2])
EDIT: changed the whitespace to be the same as the author
Related
I want to move the element at index 2 to the start of the array [1, 2, 3, 4], the resulting array should look like [3, 1, 2, 4].
My solution was to do the following
[3] + ([1, 2, 3, 4] - [3])
Is there a better way to do this?
A method that takes the first n elements from an array and rotates them by one, then adds back the remaining elements.
def rotate_first_n_right(arr, n)
arr[0...n].rotate(-1) + arr[n..-1]
end
rotate_first_n_right([1,2,3,4], 3)
# => [3, 1, 2, 4]
This does fail if we try to use it on an array that is too short, as the arr[n..-1] slice will yield nil which will cause an error when we try to add it to the first array.
We can fix this by expanding both slices into a list.
def rotate_first_n_right(arr, n)
[*arr[0...n].rotate(-1), *arr[n..-1]]
end
To see why this works, a very simple example:
[*[1, 2, 3], *nil]
# => [1, 2, 3]
A problem with you example is what happens if 3 occurs in the array more than once. E.g.
[1,2,3,3,3,4] - [3]
# => [1, 2, 4]
Not sure what you mean about "rotation" as this is not exactly a rotation but you could go with
def move_element_to_front(arr, idx)
# ruby >= 2.6 arr.dup.then {|a| a.unshift(a.delete_at(idx)) }
arr = arr.dup
arr.unshift(arr.delete_at(idx))
end
This will move the element at idx to the first position in the returned Array
def move_element_to_front(arr, idx)
[arr[idx]].concat(arr[0,idx], arr[idx+1..])
end
arr = [:dog, :cat, :pig, :hen]
move_element_to_front(arr, 2)
#=> [:pig, :dog, :cat, :hen]
move_element_to_front(arr, 0)
#=> [:dog, :cat, :pig, :hen]
move_element_to_front(arr, 3)
#=> [:hen, :dog, :cat, :pig]
The operative line of the method could alternatively be expressed
[arr[idx], *arr[0,idx], *arr[idx+1..]]
I have a numpy array, I'd like to take the 3 numbers in each row, minus them from the next row and store those values in another array.
something like
for i in array:
a = i - i+1
I know this is very wrong, but at least this gives the idea of what I want.
Obviously i+1 will just result in the value + 1 and then all I have is a = 1,1,1
When I say i+1 I mean the next in line.
So for example:
input = np.array([[4,4,5], [2,3,1],[1,2,0]])
output = np.array([2,1,4],[1,1,1]) etc....
What would be the best way to do this iteratively on thousands of rows?
IIUC, instead of looping, you can just shift your arrays 1 up using np.roll, subtract that from your original input, and take all the resulting arrays except the last (because there will be nothing to subtract from the last array):
>>> inp = np.array([[4,4,5], [2,3,1],[1,2,0]])
>>> inp
array([[4, 4, 5],
[2, 3, 1],
[1, 2, 0]])
>>> (inp - np.roll(inp,-1,axis=0))[:-1]
array([[2, 1, 4],
[1, 1, 1]])
Or, a more straightforward way would just be to use numpy indexing:
>>> inp[:-1] - inp[1:]
array([[2, 1, 4],
[1, 1, 1]])
coordinates = np.empty([0,5])
np.vstack( (coordinates, np.array([1, 2, 3, 4, 5]) ))
print coordinates # []
np.append(coordinates, np.array([1, 2, 3, 4, 5]), axis=0)
print coordinates
In the code shown above, I tried to append the array, but both approaches failed. In the first approach, the output is still empty, in the second approach, the output is an error saying
ValueError: all the input arrays must have same number of dimensions
What is wrong with my method?
You need to capture the results of numpy.vstack()
From the (Docs)
numpy.vstack(arrays, axis=0)
Returns:
stacked : ndarray
Test Code:
coordinates = np.empty([0, 5])
x = np.vstack((coordinates, np.array([1, 2, 3, 4, 5])))
print x
Results:
[[ 1. 2. 3. 4. 5.]]
I wrote a function to see if a matrix is symmetric or not:
def issymmetric(mat):
if(mat.shape[0]!=mat.shape[1]):
return 0
for i in range(mat.shape[0]):
for j in range(i):
if (mat[i][j]!=mat[j][i]):
return 0
return 1
It works well with built-in ndarrays e.g. numpy.ones:
import numpy as np
a=np.ones((5,5), int)
print issymmetric(a)
And with numpy arrays:
import numpy as np
a=np.array([[1, 2, 3], [2, 1 , 2], [3, 2, 1]])
print issymmetric(a)
But when it comes to numpy matrixes:
import numpy as np
a=np.matrix([[1, 2, 3], [2, 1 , 2], [3, 2, 1]])
print issymmetric(a)
It gaves me this error:
File "issymetry.py", line 9, in issymmetric
if (mat[i][j]!=mat[j][i]):
File "/usr/lib/python2.7/dist-packages/numpy/matrixlib/defmatrix.py", line 316, in __getitem__
out = N.ndarray.__getitem__(self, index)
IndexError: index 1 is out of bounds for axis 0 with size 1
shell returned 1
That's because There is no a[0][1]
a[0] is matrix([[1, 2, 3]]). a[0][0] is matrix([[1, 2, 3]]) too., but there is no a[0][1].
How can I fix this issue, without changing the matrix type, or the function?
In general, what is the proper way to read and update one specific cell of a numpy matrix?
It is best to use [i,j] style indexing in numpy. Often you can get by with [i][j] when using np.array, but not with np.matrix. Remember an np.matrix is always 2d.
In a shell construct a simple 2d array, and try different methods of indexing. Now try it with np.matrix arrays. Pay attention to the shape.
In [2]: A = np.arange(6).reshape(2,3)
In [3]: A[1] # short for A[1,:]
Out[3]: array([3, 4, 5]) # shape (3,)
In [4]: A[1][2] # short for A[1,:][2]
Out[4]: 5
In [5]: M=np.matrix(A)
In [6]: M[1]
Out[6]: matrix([[3, 4, 5]]) # shape (1,3), 2d
In [7]: M[1][2]
...
IndexError: index 2 is out of bounds for axis 0 with size 1
correct indexing that works with both
In [9]: A[1,2]
Out[9]: 5
In [10]: M[1,2]
Out[10]: 5
A[i][j]=... is also prone to failure when used on the LHS. It only works if the first part A[i] returns a view. If fails if it produces a copy.
I switched from Matlab/Octave to SciPy/NumPy recently, and I like it. But I found sometimes I get confused due to subtle differences.
In Matlab, when we declare a "row vector" of size 5, then we use the following command:
x = [1, 2, 3 ,4, 5] % in matlab
The size of this vector may be checked using the "size" command as shown below:
size(x)
ans =
1 5
I had assumed that the following in NumPy is doing the same thing as above.
x = np.array([1, 2, 3, 4, 5]) # in NumPy
But the size is somewhat weird.
>>> np.shape(x)
(5,)
The size is not (5, 1), but it is (5, ). What does it exactly mean? I'm not quite sure why the second element of this tuple is empty.
I checked that the following returns (5, 1)
y = np.array([[1], [2], [3], [4], [5]])
np.shape(y)
(5, 1)
Then, is "y" the same as "x" in NumPy? I assume it is not. I might be misunderstanding something, but could any one enlighten me on this topic?
Thanks!
The shape of a NumPy array is always a tuple. (5) is not a tuple since Python evaluates it to be equal to the number 5. To obtain a tuple, one must add a comma after the 5, as in (5,).
Thus, (5,) is a tuple containing 1 value, the number 5 and
(5, 1) is a tuple containing 2 values, the numbers 5 and 1.
The number of elements in the tuple equals the number dimensions of the array. In NumPy lingo, dimensions are also called "axes".
So
x = np.array([1, 2, 3, 4, 5])
is an array of shape (5,), and it has 1 dimension.
In contrast,
y = np.array([[1], [2], [3], [4], [5]])
is an array of shape (5, 1) and has 2 dimensions.
Thus, x and y are not the same.
Note in NumPy lingo, the "size" or an array refers to the number of values in the array:
In [48]: x.size
Out[48]: 5
In [49]: y.size
Out[49]: 5
NumPy arrays can "broadcast" their values to act like arrays of higher dimension. Since broadcasting can add new axes to the left side of an array's shape, an array of shape (5,) can broadcast to shape (1, 5).
Since for 2-dimensional arrays the first axis can be thought of as corresponding to the rows and the second axis the columns, a 1-dimensional array like x can behave like a 1-row, 5-column array -- i.e. a row vector.
y has shape (5, 1) which makes it a 5-row, 1-column array -- i.e. a column vector.
If you add an array of shape (1, 5) (i.e. a row vector) with an array of shape (5, 1) (i.e. a column vector), the broadcasting rules produces an array of shape (5, 5):
In [60]: x + y
Out[60]:
array([[ 2, 3, 4, 5, 6],
[ 3, 4, 5, 6, 7],
[ 4, 5, 6, 7, 8],
[ 5, 6, 7, 8, 9],
[ 6, 7, 8, 9, 10]])
If you want x to act like a column vector, you would need to add a new axis on the right. Broadcasting never does that, so you have to do it manually with x[:, np.newaxis].
Adding two column vectors produces another column vector:
In [61]: x[:, np.newaxis].shape
Out[61]: (5, 1)
In [56]: x[:, np.newaxis] + y
Out[56]:
array([[ 2],
[ 4],
[ 6],
[ 8],
[10]])