How to create a array of consecutive numbers array in numpy? - arrays

I'm looking to generate an array as follows:
array([[ 1, 2],
[ 2, 3],
[ 3, 4],
[ 4, 5],
[ 5, 6],
[ 6, 7],
[ 7, 8],
[ 8, 9],
[ 9, 10]])
Here is how I generate in NumPy:
import numpy as np
a = np.arange(1, 10)
b = np.arange(2, 11)
np.stack((a, b), axis=1)
Is there any function in NumPy that does this directly?

The shortest answer I can think of, using broadcasting black magic:
# Solution 1:
np.r_[:9][:,None]+[1,2]
# Solution 2:
np.r_['c',:9]+[1,2]
Or also using np.r_ but without broadcasting this time:
# Solution 3:
np.r_['1,2,0', :10, 1:11]
Every solution produce, as expected:
array([[ 1, 2],
[ 2, 3],
[ 3, 4],
[ 4, 5],
[ 5, 6],
[ 6, 7],
[ 7, 8],
[ 8, 9],
[ 9, 10]])

I don't know of any built-in to do this kind of arrangement, but here are some alternative solutions.
Using a half step size and np.floor:
>>> np.floor(np.arange(1.5, 10.5, .5)).reshape(9, 2)
Using np.repeat:
>>> np.repeat(np.arange(1, 11), 2)[1:-1].reshape(9, 2)
Using np.lib.stride_tricks.as_strided (imo the best method):
>>> as_strided(np.arange(1, 11), shape=(9, 2), strides=(8, 8))
Since the 2D->1D mapping you're looking to achieve is i + j = k, strides must be (1, 1) in bytes i.e. (8, 8) in bits.

Related

Confusion regarding resulting shape of a multi-dimensional slicing of a numpy array

Suppose we have
t = np.random.rand(2,3,4)
i.e., a 2x3x4 tensor.
I'm having trouble understanding why the shape of t[0][:][:2] is 2x4 rather than 3x2.
Aren't we taking the 0th, all, and the first indices of the 1st, 2nd, and 3rd dimensions, in which case that would give us a 3x2 tensor?
In [1]: t = np.arange(24).reshape(2,3,4)
In [2]: t
Out[2]:
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]]])
Select the 1st plane:
In [3]: t[0]
Out[3]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
[:] selects everything - ie. no change
In [4]: t[0][:]
Out[4]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Select first 2 rows of that plane:
In [5]: t[0][:][:2]
Out[5]:
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
While [i][j] works for integer indices, it shouldn't be used for slices or arrays. Each [] acts on the result of the previous. [:] is not a 'placeholder' for the 'middle dimension'. Python syntax and execution order applies, even when using numpy. numpy just adds an array class, and functions. It doesn't change the syntax.
Instead you want:
In [6]: t[0,:,:2]
Out[6]:
array([[0, 1],
[4, 5],
[8, 9]])
The result is the 1st plane, and first 2 columns, (and all rows). With all 3 dimensions in one [] they are applied in a coordinated manner, not sequentially.
There is a gotcha, when using a slice in the middle of 'advanced indices'. Same selection as before, but transposed.
In [8]: t[0,:,[0,1]]
Out[8]:
array([[0, 4, 8],
[1, 5, 9]])
For this you need a partial decomposition - applying the 0 first
In [9]: t[0][:,[0,1]]
Out[9]:
array([[0, 1],
[4, 5],
[8, 9]])
There is a big indexing page in the numpy docs that you need to study sooner or later.

Appending pairs of coordinates to numpy array

I need to append 1D arrays (coordinates) into a 2d array using numpy in python 3.6.
I can do this with lists using append, such as in the first example below.
mastlist =[]
i=0
for i in range (10):
i=i+1
coor = []
xcoor = i
ycoor =i*2
coor.append(xcoor)
coor.append(ycoor)
mastlist.append(coor)
print(mastlist)
But I want a more performant approach using numpy arrays. When I attempt to convert the list approach to an array (second example),
import numpy as np
i=0
for i in range (10):
i=i+1
centroid =np.append(i,i*2)
masterarray=np.append([centroid],axis=0)
print(masterarray)
print(masterarray)
I get the error below.
My error is:
TypeError: append() missing 1 required positional argument: 'values'
I would of expected an array such as:
[[1, 2], [2, 4], [3, 6], [4, 8], [5, 10], [6, 12], [7, 14], [8, 16], [9, 18], [10, 20]]
I have also fumbled with attempts using extend, vstack, and concatenate.
Any advice would be welcome.
I recommend you get single coordinate data firstly , then concatenate them. To my best knowledge, I dont think it can be done by np.append
The common method is np.concatenate, which I see it from cs231n class.
My sample codes are as follows:
import numpy as np
xcoor = np.arange(1,11,1).reshape(-1,1)
ycoor = np.arange(2,22,2).reshape(-1,1)
xycoor = np.concatenate((xcoor,ycoor),axis = 1)
print(xycoor)
Output:
[[ 1 2]
[ 2 4]
[ 3 6]
[ 4 8]
[ 5 10]
[ 6 12]
[ 7 14]
[ 8 16]
[ 9 18]
[10 20]]
Why not just use list comprehension?
import numpy as np
masterarray = np.array([[i,2*i] for i in range(1,11)])
output
array([[ 1, 2],
[ 2, 4],
[ 3, 6],
[ 4, 8],
[ 5, 10],
[ 6, 12],
[ 7, 14],
[ 8, 16],
[ 9, 18],
[10, 20]])

How to reshape an array of shape (N , N) dimension to (N , N , 3)

I have an array of shape ( 2084, 2084) i want to reshape it to (2084, 2084 , 3). I tried using np.dstack but it gives me something like this (1, 2084, 2084)
patch = (2084, 2084)
patch_new = np.dstack(patch)
How do I do it?
You missed promoting your array to 3D before depth stacking. So, you can use something like:
In [93]: patch = (2084, 2084)
In [94]: arr = np.random.random_sample(patch)
# make it as 3D array
In [95]: arr = arr[..., np.newaxis]
# and then stack it along the third dimension (say `n` times; here `3`)
In [96]: arr_3d = np.dstack([arr]*3)
In [97]: arr_3d.shape
Out[97]: (2084, 2084, 3)
Another way to do the same is (i.e. if you don't wish to promote your input array explicitly to 3D):
In [140]: arr_3d = np.dstack([arr]*3)
In [141]: arr_3d.shape
Out[141]: (2084, 2084, 3)
# sanity check
In [146]: arr_3 = np.dstack([arr[..., np.newaxis]]*3)
In [147]: arr_3.shape
Out[147]: (2084, 2084, 3)
In [148]: np.allclose(arr_3, arr_3d)
Out[148]: True
In [730]: x = np.arange(8).reshape(2,4)
In [731]: x
Out[731]:
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
Your dstack not only adds an initial dimension, it transposes the rest. That's because it treats your array as a list, np.dstack([x[0,:], x[1,:]]).
In [732]: np.dstack(x)
Out[732]:
array([[[0, 4],
[1, 5],
[2, 6],
[3, 7]]])
This is a repeat task
In [733]: np.repeat(x[...,None],3,axis=2)
Out[733]:
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]]])
Kmario, so you repeat the same array 3 times over the third dimension ?

How to delete specific rows from a numpy array using a condition?

This is the code
a = np.array([[ 0, 1],
[ 3, 11],
[4,2]])
This is what I tried
a= a[a[0]>0,:]
It works fine when I only have two elements, but anything more it throws an error.What I am trying to do is that in the first column if there's a value less than one than I need to delete that entire row.
so the expected output is
([ 3, 11],
[4,2]])
I was hoping for a solution which I could generalize even if there were more than 2 elements per item such as
([2,3,4,5],
[8,2,4,6],
[2,4,9,1],
[5,3,2,0],)
then the application of the code will give a result such as
([2,3,4,5],
[8,2,4,6],
[2,4,9,1],)
Any suggestions.
For just the first column use a[:,0] > 0 which will pull all the values from the first column and check which are > 0 or whatever condition you want:
In [50]: a = np.array([[ 0, 1],
[ 3, 11],
[4,2]])
In [51]: a[a[:,0] > 0]
Out[51]:
array([[ 3, 11],
[ 4, 2]])
You can use all if you want to check all values in each row:
In [43]: a = np.array([[ 0, 1],
[ 3, 11],
[4,2]])
In [44]: a[(a >= 0).all(axis=1)]
Out[44]:
array([[ 3, 11],
[ 4, 2]])
In [45]: a = np.array ([[2,3,4,5],
[8,2,4,6],
[2,4,9,1],
[5,3,2,0]])
In [46]: a[(a > 0).all(axis=1)]
Out[46]:
array([[2, 3, 4, 5],
[8, 2, 4, 6],
[2, 4, 9, 1]])

How to transpose an array in Python 3?

I've been scanning the forums and haven't found an answer yet that I can apply to my situation. I need to be able to take an n by n array and transpose it in Python-3. The example given is that I have this list input into the function:
[[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]] and it needs to be transposed to read:
[[4, 'a', -1], [2, 'a', -2], [1, 'a', -3]] So basically reading vertically instead of horizontally.
I CANNOT use things like zip or numpy, I have to make my own function.
Been rattling my brain at this for two nights and it's a huge headache. If anyone could help and then provide an explanation so I can learn it, I'd be grateful.
Edit:
I should add for reference sake that the argument variable is M. The function we're supposed to write is trans(M):
A one-liner:
def trans(M):
return [[M[j][i] for j in range(len(M))] for i in range(len(M[0]))]
result:
>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> trans(M)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]
# or for a non-square matrix:
>>> N = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> trans(N)
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Additional Note: If you look up the tutorial on list comprehension, one of the examples is in fact transposition of a matrix array.
A variant that should work for matrices with irregular row lengths:
m=[[3, 2, 1],
[0, 1],
[2, 1, 0]]
m_T = [ [row[c] for row in m if c < len(row)] for c in range(0, max([len(row) for row in m])) ]
Here is an in place solution that works for square matrices:
def trans(M):
n = len(M)
for i in range(n - 1):
for j in range(i + 1, n):
M[i][j], M[j][i] = M[j][i], M[i][j]
Example Usage:
def print_matrix(M):
for row in M:
for ele in row:
print(ele, end='\t')
print()
M = [[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]]
print('Original Matrix:')
print_matrix(M)
trans(M)
print('Transposed Matrix:')
print_matrix(M)
Output:
Original Matrix:
4 2 1
a a a
-1 -2 -3
Transposed Matrix:
4 a -1
2 a -2
1 a -3
y=([1,2], [3,4], [5,6])
transpose=[[row[i] for row in y] for i in range(len(y[0]))]
the output is
[[1, 3, 5], [2, 4, 6]]
You can also use the function in numpy to transpose - if you need the answer as a list it is straightforward to convert back using tolist:
from numpy import transpose
M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose(M).tolist()
the output is
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Haven't timed it (no time!) but I strongly suspect this will be a lot faster than iterators for large arrays, especially if you don't need to convert back to a list.

Resources