Shift a numpy array by an increasing value with each row - python

I have a numpy array I'll use np.ones((2,3)) as a MWE:
arr = [[1,1,1],
[1,1,1],
[1,1,1]]
I wish to shift the rows by a set integer. This will increase with the row.
Shift the 1st row by 0
shift the 5th row by 4
I imagine the row length will have to be equal for all rows giving something list this:
to give this:
arr = [[1,1,1,0,0],
[0,1,1,1,0],
[0,0,1,1,1]]
This is a MWE and the actual arrays are taken from txt files and are up to (1000x96). The important values are not just 1 but any float from 0->inf.
Is there a way of doing this?
(Extra information: these data are for 2D heatmap plotting)

Assuming an array with arbitrary values, you could use:
# add enough "0" columns for the shift
arr2 = np.c_[arr, np.zeros((arr.shape[0], arr.shape[0]-1), dtype=arr.dtype)]
# get the indices as ogrid
r, c = np.ogrid[:arr2.shape[0], :arr2.shape[1]]
# roll the values
arr2 = arr2[r, c-r]
used input:
arr = np.arange(1,10).reshape(3,3)
# array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
output:
array([[1, 2, 3, 0, 0],
[0, 4, 5, 6, 0],
[0, 0, 7, 8, 9]])

I have the following solution:
import numpy as np
arr = [[1,1,1],
[1,1,1],
[1,1,1],
[1,1,1]]
arr = np.array(arr)
shift = 1
extend = shift*(np.shape(arr)[0]-1)
arr2 = np.zeros((np.shape(arr)[0],extend+np.shape(arr)[1]))
for i,row in enumerate(arr):
arr2[i,(i*shift):(i*shift)+3] = row
print(arr2)
[[1. 1. 1. 0. 0. 0.]
[0. 1. 1. 1. 0. 0.]
[0. 0. 1. 1. 1. 0.]
[0. 0. 0. 1. 1. 1.]]

Related

Matrix element repetition bug

I'm trying to create a matrix that reads:
[0,1,2]
[3,4,5]
[6,7,8]
However, my elements keep repeating. How do I fix this?
import numpy as np
n = 3
X = np.empty(shape=[0, n])
for i in range(3):
for j in range(1,4):
for k in range(1,7):
X = np.append(X, [[(3*i) , ((3*j)-2), ((3*k)-1)]], axis=0)
print(X)
Results:
[[ 0. 1. 2.]
[ 0. 1. 5.]
[ 0. 1. 8.]
[ 0. 1. 11.]
[ 0. 1. 14.]
[ 0. 1. 17.]
[ 0. 4. 2.]
[ 0. 4. 5.]
I'm not really sure how you think your code was supposed to work. You are appending a row in X at each loop, so 3 * 3 * 7 times, so you end up with a matrix of 54 x 3.
I think maybe you meant to do:
for i in range(3):
X = np.append(X, [[3*i , 3*i+1, 3*i+2]], axis=0)
Just so you know, appending array is usually discouraged (just create a list of list, then make it a numpy array).
You could also do
>> np.arange(9).reshape((3,3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])

Find all the rectangles coordinates in a numpy 2d array ( prioritizing the vertical rectangles)

I am trying to figure out a solution for finding all the rectangles in a 2d array.
But in the mean while, I need to get the vertical ones first.
For example:
[[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 1.]
[0. 0. 1. 1. 1.]]
The desire output would be
[[0, 2, 0, 2], [2, 2, 2, 2], [1, 3, 2, 4]]
Or something like
[[1. 0. 0. 0. 0.]
[1. 1. 0. 1. 1.]
[1. 1. 1. 1. 0.]]
Output should be
[[0, 0, 0, 0], [1, 0, 2, 1], [2, 2, 2, 2], [1, 3, 2, 3], [1, 4, 1, 4]]
In other words, if it's a horizontal rectangle of the height of only 1, it is viewed as multiple 11.
I am kind of stuck on the logic which should proceed first, my results prioritize the horizontal ones and have troubles dealing with zeros when encounter a 2*2 or above rectangle.
UPDATE
A rectangle in here means an area composed of 1s in the 2d array. However when something like
[[0. 0. 0. 0. 0.]
[0. 0. 0. 1. 1.]
[0. 0. 0. 1. 0.]]
happens, the output should be
[[1, 3, 2, 3], [1, 4, 1, 4]]
instead of
[[1, 3, 1, 4], [2, 3, 2, 3]]
1*1 counts as a rectangle too
The code I have for now looks like this
def solve2(grid):
output = []
visited = set()
for j in range(len(grid[0])):
for i in range(len(grid)):
if (i,j) in visited:
continue
visited.add((i,j))
if grid[i][j] == 1:
s_row, s_col = i, j
e_row, e_col = i,j
while e_col < len(grid[0]) and grid[i][e_col]:
while e_row < len(grid) and grid[e_row][j]:
e_row += 1
e_col += 1
for x in range(s_row, e_row):
for y in range(s_col, e_col):
visited.add((x,y))
e_row -= 1
e_col -= 1
output.append([s_row, s_col, e_row, e_col])
return output

Numpy - Declare a specific nx1 array

I'm using numpy in python , in order to create a nx1 matrix . I want the 1st element of the matrix to be 3 , the 2nd -1 , then the n-1 element -1 again and at the end the n element 3. All the in between elements , i.e. from element 3 to element n-2 should be 0. I've made a drawing of the mentioned matrix , is like this :
I'm fairly new to python and using numpy but seems like a great tool for managing matrices. What I've tried so far is creating the nx1 array (giving n some value) and initializing it to 0 .
import numpy as np
n = 100
I = np.arange(n)
matrix = np.row_stack(0*I)
print("\Matrix is \n",matrix)
Any clues to how i proceed? Or what routine to use ?
Probably the simplest way is to just do the following:
import numpy as np
n = 10
a = np.zeros(n)
a[0] = 3
a[1] = -1
a[len(a)-1] = 3
a[len(a)-2] = -1
>>print(a)
output: [ 3. -1. 0. 0. 0. 0. 0. 0. -1. 3.]
Hope this helps ;)
In [97]: n=10
In [98]: arr = np.zeros(n,int)
In [99]: arr[[0,-1]]=3; arr[[1,-2]]=-1
In [100]: arr
Out[100]: array([ 3, -1, 0, 0, 0, 0, 0, 0, -1, 3])
Easily changed to (n,1):
In [101]: arr[:,None]
Out[101]:
array([[ 3],
[-1],
[ 0],
[ 0],
[ 0],
[ 0],
[ 0],
[ 0],
[-1],
[ 3]])
I guess something that works is :
import numpy as np
n = 100
I = np.arange(n)
matrix = np.row_stack(0*I)
matrix[0]=3
matrix[1]=-1
matrix[n-2]=-1
matrix[n-1]=3
print("\Matrix is \n",matrix)

How to initialise a Numpy array of numpy arrays

I have a numpy array D of dimensions 4x4
I want a new numpy array based on an user defined value v
If v=2, the new numpy array should be [D D].
If v=3, the new numpy array should be [D D D]
How do i initialise such a numpy array as numpy.zeros(v) dont allow me to place arrays as elements?
If I understand correctly, you want to take a 2D array and tile it v times in the first dimension? You can use np.repeat:
# a 2D array
D = np.arange(4).reshape(2, 2)
print D
# [[0 1]
# [2 3]]
# tile it 3 times in the first dimension
x = np.repeat(D[None, :], 3, axis=0)
print x.shape
# (3, 2, 2)
print x
# [[[0 1]
# [2 3]]
# [[0 1]
# [2 3]]
# [[0 1]
# [2 3]]]
If you wanted the output to be kept two-dimensional, i.e. (6, 2), you could omit the [None, :] indexing (see this page for more info on numpy's broadcasting rules).
print np.repeat(D, 3, axis=0)
# [[0 1]
# [0 1]
# [0 1]
# [2 3]
# [2 3]
# [2 3]]
Another alternative is np.tile, which behaves slightly differently in that it will always tile over the last dimension:
print np.tile(D, 3)
# [[0, 1, 0, 1, 0, 1],
# [2, 3, 2, 3, 2, 3]])
You can do that as follows:
import numpy as np
v = 3
x = np.array([np.zeros((4,4)) for _ in range(v)])
>>> print x
[[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]]
Here you go, see if this works for you.
import numpy as np
v = raw_input('Enter: ')
To intialize the numpy array of arrays from user input (obviously can be whatever shape you're wanting here):
b = np.zeros(shape=(int(v),int(v)))
I know this isn't initializing a numpy array but since you mentioned wanting an array of [D D] if v was 2 for example, just thought I'd throw this in as another option as well.
new_array = []
for x in range(0, int(v)):
new_array.append(D)

Filling a 2D list with user input where value of column increases by 1 iteratively

I asks the user to input the values of ROW to fill a 2D list. The value of column will be iterativley increase by 1.
list2D = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
user input = [1,3,0,2] ##indexes of rows as well as values
i.e:
0th column the row = 1
1 column row = 3
2 column row = 0
3 column row = 2
So the new list will be:
newList = [[0,0,**0**,0],[1,0,0,0],[0,0,0,2],[0,3,0,0]]
How to do this?
list2D = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
user_input = [1,3,0,2]
for col,row in enumerate(user_input):
list2D[row][col] = row
print(list2D)
# [[0, 0, 0, 0], [1, 0, 0, 0], [0, 0, 0, 2], [0, 3, 0, 0]]
or, if you do not wish to modify list2D:
import copy
list2D = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
user_input = [1,3,0,2]
newList = copy.deepcopy(list2D)
for col,row in enumerate(user_input):
newList[row][col] = row
or, using numpy:
import numpy as np
list2D = np.zeros((4,4))
user_input = [1,3,0,2]
list2D[user_input,range(4)] = user_input
print(list2D)
# [[ 0. 0. 0. 0.]
# [ 1. 0. 0. 0.]
# [ 0. 0. 0. 2.]
# [ 0. 3. 0. 0.]]

Categories