I am new to python, and I am stuck on a basic question. I want to enter a matrix:
[1 2 3
4 5 6
10 9 1]
but I want it to be in the form:
[[1,2,3], [4,5,6],[10,9,1]]
Do these representations have any specific names? What does that comma and double square brackets denote? I know this is a really silly question, but how do you convert it to the desired form?
Two ways:
1) Plain python
First step: Generate a list of 9 numbers
import random
randomlist = []
for i in range(0, 9):
n = random.randint(1, 30) # change for the value you desire here... for the moment it will give you a random numbers btween 0 to 9
randomlist.append(n)
print(randomlist)
Second step: make it to desired reshape (list of three lists) :
desiredoutput = [randomlist[x:x+3] for x in range(0, len(randomlist), 3)]
print(desiredoutput)
2) Using numpy
Reproduce the first step of solution 1 to get an array of random numbers. Then:
import numpy
sourcelist = numpy.asarray(randomlist)
desiredoutput = sourcelist.reshape(3, 3)
What you want to use is python numpy library which allows you to reshape your arrays into a form you want, not python lists
import numpy as np
a = np.asarray([1, 2, 3, 4, 5, 6, 9, 10, 1])
print(a)
# [ 1 2 3 4 5 6 9 10 1]
b = a.reshape(3, 3)
print(b)
# [[ 1 2 3]
# [ 4 5 6]
# [ 9 10 1]]
Related
I'm working on a code and a question just pop up in my head. So basically I have a 2D numpy array with shape
L,W = (4, 4) (this is just an example, the array, can be much bigger).
What I need is to create 3D array with elements from the 2D numpy array, where the elements in each cell of the output are: array[i:i+l, j:j+w](the elements of the subarray of dimension (l,w) starting from i, j position): output[i,j,:] = array[i:i+l,j:j+w].reshape(l*w,)
I thought about non-vectorized solution :
import numpy as np
L = 4
W = 4
array = np.arange(16).reshape(L,W)
l= 2
w = 2
subarrays_elements = []
for i in range(L-(l-1)):
for j in range(W-(w-1)):
subarrays_elements.append(array[i:i+l,j:j+w].reshape(l*w,))
output = np.array(subarrays_elements).reshape(L-(l-1),W-(w-1),l*w)
the shape of the output is W-(w-1),L-(l-1),l*w,because we can't get a (l, w) subarray for the last l-1 rows and for w-1 columns.
The expected output would be array with (3,3,4):
expected_output = np.array([[[0 1 4 5],
[1 2 5 6],
[2 3 6 7]],
[[4 5 8 9],
[5 6 9 10],
[6 7 10 11]],
[[8 9 12 13],
[9 10 13 14],
[10 11 14 15]]])
I need solutions using only numpy and with vectorization, because I have a huge array, so any help will be appreciated, thank you!
This kind of problem is quite similar to getting the input for a convolutional layer in a neural network, so you can use the same tool, which is numpy.lib.stride_tricks.sliding_window_view.
Here's an example:
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view
L = 4
W = 4
array = np.arange(L * W).reshape(L,W)
l = 2
w = 2
new_length = L-(l-1)
new_width = W-(w-1)
output = sliding_window_view(array, window_shape=[l, w]).reshape(new_length, new_width, l*w)
In theory, a sliding window should take almost no time at all, because it's just manipulating array strides and not copying data, but in this case the reshape forces it to make a complete copy of the array. On my computer this runs at about 50 million array elements per second on large arrays.
I'm trying to index a 2-dimensional array to certain values using numpy.where(), but unless I am indexing in the first index without a : slice it always increases the dimension. I can't seem to find an explanation for this in the documentation.
For example, say I have an array a:
a = np.arange(20)
a = np.reshape(a,(4,5))
print("a = ",a)
print("a shape = ", a.shape)
Output:
a = [[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
a shape = (4, 5)
If I have two indexing arrays, one in the 'x' direction and one in the 'y' direction:
x = np.arange(5)
y = np.arange(4)
xindx = np.where((x>=2)&(x<=4))
yindx = np.where((y>=1)&(y<=2))
and then index a using the 'y' index like so there's no problem:
print(a[yindx])
print(a[yindx].shape)
Output:
[[ 5 6 7 8 9]
[10 11 12 13 14]]
(2, 5)
But if I have : in one of the indices then I have an extra dimension of size 1:
print(a[yindx,:])
print(a[yindx,:].shape)
print(a[:,xindx])
print(a[:,xindx].shape)
Output:
[[[ 5 6 7 8 9]
[10 11 12 13 14]]]
(1, 2, 5)
[[[ 2 3 4]]
[[ 7 8 9]]
[[12 13 14]]
[[17 18 19]]]
(4, 1, 3)
I run into this issue with one-dimensional arrays, too. How do I fix this?
If xindx and yindx were numpy arrays, the result would be as expected. However, they are tuples with a single value.
Easiest (and pretty dumb) fix:
xindx = np.where((x>=2)&(x<=4))[0]
yindx = np.where((y>=1)&(y<=2))[0]
With only the condition given, np.where will return indices of matching elements in a tuple. This use is explicitly discouraged in the documentation.
More realistically, you probably need something like:
xindx = np.arange(2, 5)
yindx = np.arange(1, 3)
... but it really depends on the context we don't see
I'm looking for an efficient way to do the following with Numpy:
Given a array counts of positive integers containing for instance:
[3, 1, 0, 6, 3, 2]
I would like to generate another array containing the indices of the first one, where the index i is repeated counts[i] times:
[0 0 0 1 3 3 3 3 3 3 4 4 4 5 5]
My problem is that this array is potentially very large and I'm looking for a vectorial (or fast) way to do this.
You can do it with numpy.repeat:
import numpy as np
arr = np.array([3, 1, 0, 6, 3, 2])
repix = np.repeat(np.arange(arr.size), arr)
print(repix)
Output:
[0 0 0 1 3 3 3 3 3 3 4 4 4 5 5]
I have an array :
a = np.array([1,2,3,4,5,6,7,8])
The array may be reshaped to a = np.array([[1,2,3,4],[5,6,7,8]]), whatever is more convenient.
Now, I have an array :
b = np.array([[11,22,33,44], [55,66,77,88]])
I want to replace to each of these elements the corresponding elements from a.
The a array will always hold as many elements as b has.
So, array b will be :
[1,2,3,4], [5,6,7,8]
Note, that I must keep each b subarray dimension to (4,). I don't want to change it.So, the idx will take values from 0 to 3.I want to make a fit to every four values.
I am struggling with reshape, split,mask ..etc and I can't figure a way to do it.
import numpy as np
#a = np.array([[1,2,3,4],[5,6,7,8]])
a = np.array([1,2,3,4,5,6,7,8])
b = np.array([[11,22,33,44], [55,66,77,88]])
for arr in b:
for idx, x in enumerate(arr):
replace every arr[idx] with corresponding a value
For your current case, what you want is probably:
b, c = list(a.reshape(2, -1))
This isn't the cleanest, but it is a one-liner. Turn your 1D array into a 2D array with with the first dimension as 2 with reshape(2, -1), then list splits it along the first dimension so you can directly assign them to b, c
You can also do it with the specialty function numpy.split
b, c = np.split(a, 2)
EDIT: Based on accepted solution, vectorized way to do this is
b = a.reshape(b.shape)
The following worked for me:
i = 0
for arr in b:
for idx, x in enumerate(arr):
arr[idx] = a[i]
print(arr[idx])
i += 1
Output (arr[idx]): 1 2 3 4 5 6 7 8
If you type print(b) it'll output [[1 2 3 4] [5 6 7 8]]
b = a[:len(a)//2]
c = a[len(a)//2:]
Well, I'm quite new to Python but this worked for me:
for i in range (0, len(a)//2):
b[i] = a[i]
for i in range (len(a)//2,len(a)):
c[i-4] = a[i]
by printing the 3 arrays I have the following output:
[1 2 3 4 5 6 7 8]
[1 2 3 4]
[5 6 7 8]
But I would go for Daniel's solution (the split one): 1 liner, using numpy API, ...
can someone explain me how to slice a numpy.array at runtime?
I don't know the rank (number of dimensions) at 'coding time'.
A minimal example:
import numpy as np
a = np.arange(16).reshape(4,4) # 2D matrix
targetsize = [2,3] # desired shape
b_correct = dynSlicing(a, targetsize)
b_wrong = np.resize(a, targetsize)
print a
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
print b_correct
[[0 1 2]
[4 5 6]]
print b_wrong
[[0 1 2]
[3 4 5]]
And my ugly dynSlicing():
def dynSlicing(data, targetsize):
ndims = len(targetsize)
if(ndims==1):
return data[:targetsize[0]],
elif(ndims==2):
return data[:targetsize[0], :targetsize[1]]
elif(ndims==3):
return data[:targetsize[0], :targetsize[1], :targetsize[2]]
elif(ndims==4):
return data[:targetsize[0], :targetsize[1], :targetsize[2], :targetsize[3]]
Resize() will not do the job since it flats the array before dropping elements.
Thanks,
Tebas
Passing a tuple of slice objects does the job:
def dynSlicing(data, targetsize):
return data[tuple(slice(x) for x in targetsize)]
Simple solution:
b = a[tuple(map(slice,targetsize))]
You can directly 'change' it. This is due to the nature of arrays only allowing backdrop.
Instead you can copy a section, or even better create a view of the desired shape:
Link