I am working in Python and I have a NumPy array like this:
[1,5,9]
[2,7,3]
[8,4,6]
How do I stretch it to something like the following?
[1,1,5,5,9,9]
[1,1,5,5,9,9]
[2,2,7,7,3,3]
[2,2,7,7,3,3]
[8,8,4,4,6,6]
[8,8,4,4,6,6]
These are just some example arrays, I will actually be resizing several sizes of arrays, not just these.
I'm new at this, and I just can't seem to wrap my head around what I need to do.
#KennyTM's answer is very slick, and really works for your case but as an alternative that might offer a bit more flexibility for expanding arrays try np.repeat:
>>> a = np.array([[1, 5, 9],
[2, 7, 3],
[8, 4, 6]])
>>> np.repeat(a,2, axis=1)
array([[1, 1, 5, 5, 9, 9],
[2, 2, 7, 7, 3, 3],
[8, 8, 4, 4, 6, 6]])
So, this accomplishes repeating along one axis, to get it along multiple axes (as you might want), simply nest the np.repeat calls:
>>> np.repeat(np.repeat(a,2, axis=0), 2, axis=1)
array([[1, 1, 5, 5, 9, 9],
[1, 1, 5, 5, 9, 9],
[2, 2, 7, 7, 3, 3],
[2, 2, 7, 7, 3, 3],
[8, 8, 4, 4, 6, 6],
[8, 8, 4, 4, 6, 6]])
You can also vary the number of repeats for any initial row or column. For example, if you wanted two repeats of each row aside from the last row:
>>> np.repeat(a, [2,2,1], axis=0)
array([[1, 5, 9],
[1, 5, 9],
[2, 7, 3],
[2, 7, 3],
[8, 4, 6]])
Here when the second argument is a list it specifies a row-wise (rows in this case because axis=0) repeats for each row.
>>> a = numpy.array([[1,5,9],[2,7,3],[8,4,6]])
>>> numpy.kron(a, [[1,1],[1,1]])
array([[1, 1, 5, 5, 9, 9],
[1, 1, 5, 5, 9, 9],
[2, 2, 7, 7, 3, 3],
[2, 2, 7, 7, 3, 3],
[8, 8, 4, 4, 6, 6],
[8, 8, 4, 4, 6, 6]])
Unfortunately numpy does not allow fractional steps (as far as I am aware). Here is a workaround. It's not as clever as Kenny's solution, but it makes use of traditional indexing:
>>> a = numpy.array([[1,5,9],[2,7,3],[8,4,6]])
>>> step = .5
>>> xstop, ystop = a.shape
>>> x = numpy.arange(0,xstop,step).astype(int)
>>> y = numpy.arange(0,ystop,step).astype(int)
>>> mg = numpy.meshgrid(x,y)
>>> b = a[mg].T
>>> b
array([[1, 1, 5, 5, 9, 9],
[1, 1, 5, 5, 9, 9],
[2, 2, 7, 7, 3, 3],
[2, 2, 7, 7, 3, 3],
[8, 8, 4, 4, 6, 6],
[8, 8, 4, 4, 6, 6]])
(dtlussier's solution is better)
Related
i have a doubt. There is an efficient way to sum all neighbors of a numpy matrix without using several conditions?
This is an example:
array([[5, 4, 8, 3, 1, 4, 3, 2, 2, 3],
[2, 7, 4, 5, 8, 5, 4, 7, 1, 1],
[5, 2, 6, 4, 5, 5, 6, 1, 7, 3],
[6, 1, 4, 1, 3, 3, 6, 1, 4, 6],
[6, 3, 5, 7, 3, 8, 5, 4, 7, 8],
[4, 1, 6, 7, 5, 2, 4, 6, 4, 5],
[2, 1, 7, 6, 8, 4, 1, 7, 2, 1],
[6, 8, 8, 2, 8, 8, 1, 1, 3, 4],
[4, 8, 4, 6, 8, 4, 8, 5, 5, 4],
[5, 2, 8, 3, 7, 5, 1, 5, 2, 6]])
When I run m[0][-1] it returns me 3 and not an error, so if I want to add 1 to all neighbors of a value I need to use a lot of conditions because I can't just use m[0][-1] because in this case and in the other cases of the corners it returns me just a " False neighbor"
IIUC, you want to add 1 to each neighbour of a cell with a given value.
For the example, let's add 1 to each cell in the neighborhood of a 7:
from scipy.signal import convolve2d
v = np.array([[1,1,1],[1,0,1],[1,1,1]])
a + convolve2d(a==7, v, mode='same')
output:
array([[6, 5, 9, 3, 1, 4, 4, 3, 3, 3],
[3, 7, 5, 5, 8, 5, 5, 8, 3, 2],
[6, 3, 7, 4, 5, 5, 7, 3, 8, 4],
[6, 1, 5, 2, 4, 3, 6, 3, 6, 8],
[6, 3, 7, 8, 5, 8, 5, 5, 7, 9],
[4, 2, 9, 9, 7, 2, 5, 8, 6, 6],
[2, 2, 8, 8, 9, 4, 2, 7, 3, 1],
[6, 9, 9, 3, 8, 8, 2, 2, 4, 4],
[4, 8, 4, 7, 9, 5, 8, 5, 5, 4],
[5, 2, 8, 4, 7, 6, 1, 5, 2, 6]])
In addition to the good #mozway solution, one very efficient solution is to use the Numba stencil decorator combined with a parallel execution. Here is an example:
import numba as nb
# parallel=True is only useful for quite-big arrays
#nb.njit(parallel=True)
def kernel(v):
cond = np.zeros((v.shape[0]+2, v.shape[1]+2), dtype=np.bool_)
cond[1:-1, 1:-1] = v == 7
res = nb.stencil(lambda c: c[-1,-1]+c[-1,0]+c[-1,1]+c[0,-1]+c[0,1]+c[1,-1]+c[1,0]+c[1,1])(cond)
return v + res[1:-1, 1:-1]
kernel(m)
An even faster solution consist in working in-place (using v += res instead of the return v + res). Here are the performance results for a 2000x2000 integer array on my 6-core machine:
scipy.signal.convolve2d: 124 ms
Numba out-of-place: 20 ms
Numba in-place: 15 ms
Note that the first call to kernel is slower due to the compilation time.
I also got a similar speed-up for smaller arrays (200x200).
I have an array like this:
a = [[ 8, 7, 6, 5, 9],
[1, 2, 1, 6, 4],
[4, 2, 5, 4, 2]]`
I want to change the order of that array based on second row with an order like this:
b = [2, 6, 1, 1, 4]
So, I want the result becomes like this:
a = [[7, 5, 8, 6, 9],
[2, 6, 1, 1, 4],
[2, 4, 4, 5, 2]]
How can I solve this problem in Python?
a = [[ 8, 7, 6, 5, 9],
[1, 2, 1, 6, 4],
[4, 2, 5, 4, 2]]
a[1] = [2, 6, 1, 1, 4]
Try that.
In this answer, I'm making the following two assumptions:
All sub-lists are 5 elements in length
The desired logic is to move the 2nd and 4th elements to be 1st and 2nd respectively
If both of the assumptions made above are true, you can use list comprehension on a nested list, and create a list to specify how the lists should be reordered.
a = [[8, 7, 6, 5, 9],
[1, 2, 1, 6, 4],
[4, 2, 5, 4, 2]]
new_ord = [1, 3, 0, 2, 4]
b = [[l[i] for i in new_ord] for l in a]
print(b) #prints: [[7, 5, 8, 6, 9], [2, 6, 1, 1, 4], [2, 4, 4, 5, 2]]
I have a 2D array, and I need to make it into a 3D array - with the next layer starting with the second row of the first layer.
This is my best attempt to visually show what I want to do, with four 'layers':
# original array
dat = np.array([[0, 0, 0, 0, 9]
[1, 1, 1, 1, 9],
[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9],
[7, 7, 7, 7, 9],
[8, 8, 8, 8, 9]], np.int32
)
#dat.shape
#(8, 5)
layers = 4
# new 3d array
# first 'layer'
[0, 0, 0, 0, 9],
[1, 1, 1, 1, 9],
[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9]
# second 'layer'
[1, 1, 1, 1, 9],
[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9]
# third 'layer'
[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9],
[7, 7, 7, 7, 9]
# fourth 'layer'
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9],
[7, 7, 7, 7, 9],
[8, 8, 8, 8, 9]
# new shape: (rows, layers, columns)
#dat.shape
#(6, 4, 5)
I realize my visual representation of the layers might not be the way I say it is at the end, but that is the shape that I'm trying to get it in.
Solutions that I've tried include a variation of np.repeat(dat[:, :, np.newaxis], steps, axis=2) but for some reason I struggle once it's more than two dimensions.
Appreciate any help!
Approach #1: Here's one approach using broadcasting -
layers = 4
L = dat.shape[0]-layers+1
out = dat[np.arange(L) + np.arange(layers)[:,None]]
If you actually need a (6,4,5) shaped array, we would need slight modification :
out = dat[np.arange(L)[:,None] + np.arange(layers)]
Approach #2: Here's another with NumPy strides -
strided = np.lib.stride_tricks.as_strided
m,n = dat.strides
N = dat.shape[1]
out = strided(dat, shape = (layers,L,N), strides= (m,N*n,n))
For (6,4,5) shaped output array,
out = strided(dat, shape = (L,layers,N), strides= (N*n,m,n))
Note that this second method would create a view into input array dat and is very efficient to be created. If you need a copy instead, append .copy() at the end : out.copy().
Sample output for (6,4,5) output -
In [267]: out[:,0,:]
Out[267]:
array([[0, 0, 0, 0, 9],
[1, 1, 1, 1, 9],
[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9]])
In [268]: out[:,1,:]
Out[268]:
array([[1, 1, 1, 1, 9],
[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9]])
In [269]: out[:,2,:]
Out[269]:
array([[2, 2, 2, 2, 9],
[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9],
[7, 7, 7, 7, 9]])
In [270]: out[:,3,:]
Out[270]:
array([[3, 3, 3, 3, 9],
[4, 4, 4, 4, 9],
[5, 5, 5, 5, 9],
[6, 6, 6, 6, 9],
[7, 7, 7, 7, 9],
[8, 8, 8, 8, 9]])
I m a little new to python. I have a function named featureExtraction which returns a 1-D array for an image. I need to stack all such 1-d arrays row wise to form a 2-d array. I have the following equivalent code in MATLAB.
I1=imresize(I,[256 256]);
Features(k,:) = featureextraction(I1);
featureextraction returns a 1-d row vector which is stacked row-wise to form a 2-d array. What is the equivalent code snippet in python?
Thank You in advance.
Not sure what you're looking for, but maybe vstack or column_stack?
>>> np.vstack((a,a,a))
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> np.column_stack((a,a,a))
array([[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5],
[6, 6, 6],
[7, 7, 7],
[8, 8, 8],
[9, 9, 9]])
Or even just np.array:
>>> np.array([a,a,a])
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
You can use numpy.vstack():
a = np.array([1,2,3])
np.vstack((a,a,a))
#array([[1, 2, 3],
# [1, 2, 3],
# [1, 2, 3]])
I use genfromtxt to read in an array from a text file and i need to split this array in half do a calculation on them and recombine them. However i am struggling with recombining the two arrays. here is my code:
X2WIN_IMAGE = np.genfromtxt('means.txt').T[1]
X2WINa = X2WIN_IMAGE[0:31]
z = np.mean(X2WINa)
X2WINa = X2WINa-z
X2WINb = X2WIN_IMAGE[31:63]
ww = np.mean(X2WINb)
X2WINb = X2WINb-ww
X2WIN = str(X2WINa)+str(X2WINb)
print X2WIN
How do i go about recombining X2WINa and X2WINb in one array? I just want one array with 62 components
X2WINc = np.append(X2WINa, X2WINb)
if you want to combine row-wise use np.vstack(), and if column-wise use np.hstack(). Example:
np.hstack( (np.arange(10), np.arange(10)) )
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.vstack( (np.arange(10), np.arange(10)) )
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
combined_array = np.concatenate((X2WINa, X2Winb))
And another one using numpy.r_:
X2WINc = np.r_[X2WINa,X2WINb]
e.g.:
>>> import numpy as np
>>> np.r_[np.arange(10),np.arange(10)]
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
There's also np.c_ to column stack:
>>> np.c_[np.arange(10),np.arange(10)]
array([[0, 0],
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5],
[6, 6],
[7, 7],
[8, 8],
[9, 9]])