Related
In what I am working on, I have two numpy matrices, both the same size, filled with 0's and 1's for simplicity (but let's say it could be filled with any numbers). What I would like to know is a way to extract, from these two matrices, the position of the 1's that exist in the same position in both matrices.
For example, if I have the following two matrices and value
a = np.array([[0, 0, 0, 1, 0, 1],
[1, 1, 0, 1, 1, 1],
[1, 0, 1, 1, 0, 1],
[1, 0 ,1, 1, 1, 0],
[0, 0, 1, 0, 0, 0]])
b = np.array([[0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 0]])
value = 1
then I would like a way to somehow get the information of all the locations where the value "1" exists in both matrices, i.e.:
result = [(0,5),(1,1),(2,3),(4,2)]
I guess the result could be thought of as an intersection, but in my case the position is important which is the reason I don't think np.intersect1d() would be much help. In the actual matrices I am working with, they are on the order of about 10,000 by 10,000, so this list would probably be a lot longer.
Thanks in advance for any help!
You could use numpy.argwhere:
import numpy as np
a = np.array([[0, 0, 0, 1, 0, 1],
[1, 1, 0, 1, 1, 1],
[1, 0, 1, 1, 0, 1],
[1, 0, 1, 1, 1, 0],
[0, 0, 1, 0, 0, 0]])
b = np.array([[0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 0]])
result = np.argwhere(a & b)
print(result)
Output
[[0 5]
[1 1]
[2 3]
[2 5]
[4 2]]
I found a question in glassdoor. I do not have additional clarification
Input : an int array [1,0,0,1,1,0,0,1,0,1,0,0,0,1]
you have to come up with a program that will give all possible subsets of the array based on the pattern.
Pattern restrictions were the string array should start with 1 and end with 1. So there will be many sub arrays like from index 0 to 3 and 0 to 4 and index 7 to 9
To solve this I was thinking of using 2 for loops and if both cases the values are equal to 1 then print them.
v=[1,0,0,1,1,0,0,1,0,1,0,0,0,1]
resultList=[]
for i in range(0,len(v)-1):
for j in range(i+1, len(v)):
if v[i]==1 and v[j]==1:
r=v[i:j]
resultList.append(r)
print(resultList)
Output:[[1, 0, 0], [1, 0, 0, 1], [1, 0, 0, 1, 1, 0, 0], [1, 0, 0, 1, 1, 0, 0, 1, 0], [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0], [1], [1, 1, 0, 0],
I only see 1 correct value so far in output [1, 0, 0, 1]. Should I have used set instead of list? I tried that but that approach did not work either. Can someone kindly give some directions on how to solve this problem?
Thanks for your time.
You can use itertools.combinations to pick 2 indices where the values are non-zeroes in the list:
from itertools import combinations
a = [1,0,0,1,1,0,0,1,0,1,0,0,0,1]
[a[i: j + 1] for i, j in combinations((i for i, n in enumerate(a) if n), 2)]
This returns:
[[1, 0, 0, 1], [1, 0, 0, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1], [1, 0, 0, 1, 1, 0, 0, 1, 0, 1], [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1], [1, 1], [1, 1, 0, 0, 1], [1, 1, 0, 0, 1, 0, 1], [1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1], [1, 0, 0, 1], [1, 0, 0, 1, 0, 1], [1, 0, 0, 1, 0, 1, 0, 0, 0, 1], [1, 0, 1], [1, 0, 1, 0, 0, 0, 1], [1, 0, 0, 0, 1]]
The probelm is in v[i:j]. Change v[i:j] to v[i:j+1]
Trying to make my code more efficient and readable and i'm stuck. Assume I want to build something like a chess board, with alternating black and white colors on an 8x8 grid. So, using numpy, I have done this:
import numpy as np
board = np.zeros((8,8), np.int32)
for ri in range(8):
for ci in range(8):
if (ci + ri) % 2 == 0:
board[ri,ci] = 1
Which nicely outputs:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]], dtype=int32)
That I can then parse as white squares or black squares. However, in practice my array is much larger, and this way is very inefficient and unreadable. I assumed numpy already has this figured out, so I tried this:
board = np.zeros(64, np.int32)
board[::2] = 1
board = board.reshape(8,8)
But that output is wrong, and looks like this:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 0]], dtype=int32)
Is there a better way to achieve what I want that works efficiently (and preferably, is readable)?
Note: i'm not attached to 1's and 0's, this can easily be done with other types of values, even True/False or strings of 2 kinds, as long as it works
Here's one approach using slicing with proper starts and stepsize of 2 in two steps -
board = np.zeros((8,8), np.int32)
board[::2,::2] = 1
board[1::2,1::2] = 1
Sample run -
In [229]: board = np.zeros((8,8), np.int32)
...: board[::2,::2] = 1
...: board[1::2,1::2] = 1
...:
In [230]: board
Out[230]:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]], dtype=int32)
Other tricky ways -
1) Broadcasted comparison :
In [254]: r = np.arange(8)%2
In [255]: (r[:,None] == r)*1
Out[255]:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]])
2) Broadcasted addition :
In [279]: r = np.arange(8)
In [280]: 1-(r[:,None] + r)%2
Out[280]:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]])
Just found out an alternative answer by myself, so posting it here for future reference to anyone who's interested:
a = np.array([[1,0],[0,1]])
b = np.tile(a, (4,4))
Results:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]])
I think the following is also a good way of doing it for a variable input
import sys
lines = sys.stdin.readlines()
n = int(lines[0])
import numpy as np
a = np.array([[1,0], [0,1]],dtype=np.int)
outputData= np.tile(a,(n//2,n//2))
print(outputData)
You can achieve this for single even input number n
import numpy as np
i = np.eye(2)
i = i[::-1]
k = np.array(i, dtype = np.int)
print(np.tile(k,(n//2,n//2)))
I tried and found this to be shorter one for any giver number:
n = int(input())
import numpy as np
c = np.array([[0,1], [1, 0]])
print(np.tile(c, reps=(n//2, n//2)))
I'm trying to find an elegant way to find the max value in a two-dimensional array.
for example for this array:
[0, 0, 1, 0, 0, 1] [0, 1, 0, 2, 0, 0][0, 0, 2, 0, 0, 1][0, 1, 0, 3, 0, 0][0, 0, 0, 0, 4, 0]
I would like to extract the value '4'.
I thought of doing a max within max but I'm struggling in executing it.
Another way to solve this problem is by using function numpy.amax()
>>> import numpy as np
>>> arr = [0, 0, 1, 0, 0, 1] , [0, 1, 0, 2, 0, 0] , [0, 0, 2, 0, 0, 1] , [0, 1, 0, 3, 0, 0] , [0, 0, 0, 0, 4, 0]
>>> np.amax(arr)
Max of max numbers (map(max, numbers) yields 1, 2, 2, 3, 4):
>>> numbers = [0, 0, 1, 0, 0, 1], [0, 1, 0, 2, 0, 0], [0, 0, 2, 0, 0, 1], [0, 1, 0, 3, 0, 0], [0, 0, 0, 0, 4, 0]
>>> map(max, numbers)
<map object at 0x0000018E8FA237F0>
>>> list(map(max, numbers)) # max numbers from each sublist
[1, 2, 2, 3, 4]
>>> max(map(max, numbers)) # max of those max-numbers
4
Not quite as short as falsetru's answer but this is probably what you had in mind:
>>> numbers = [0, 0, 1, 0, 0, 1], [0, 1, 0, 2, 0, 0], [0, 0, 2, 0, 0, 1], [0, 1, 0, 3, 0, 0], [0, 0, 0, 0, 4, 0]
>>> max(max(x) for x in numbers)
4
How about this?
import numpy as np
numbers = np.array([[0, 0, 1, 0, 0, 1], [0, 1, 0, 2, 0, 0], [0, 0, 2, 0, 0, 1], [0, 1, 0, 3, 0, 0], [0, 0, 0, 0, 4, 0]])
print(numbers.max())
4
>>> numbers = [0, 0, 1, 0, 0, 1], [0, 1, 0, 2, 0, 0], [0, 0, 2, 0, 0, 1], [0, 1, 0, 3, 0, 0], [0, 0, 0, 0, 4, 0]
You may add key parameter to max as below to find Max value in a 2-D Array/List
>>> max(max(numbers, key=max))
4
One very easy solution to get both the index of your maximum and your maximum could be :
numbers = np.array([[0,0,1,0,0,1],[0,1,0,2,0,0],[0,0,2,0,0,1],[0,1,0,3,0,0],[0,0,0,0,4,0]])
ind = np.argwhere(numbers == numbers.max()) # In this case you can also get the index of your max
numbers[ind[0,0],ind[0,1]]
This approach is not as intuitive as others but here goes,
numbers = [0, 0, 1, 0, 0, 1], [0, 1, 0, 2, 0, 0], [0, 0, 2, 0, 0, 1], [0, 1, 0, 3, 0, 0], [0, 0, 0, 0, 4, 0]
maximum = -9999
for i in numbers:
maximum = max(maximum,max(i))
return maximum"
This must be something that is really simple, but I could not fix it.
I want to do a matrix type transpose with native python list of list (i.e., without using numpy or pandas). Code is show following. I am having a hard time trying to figure out where it is wrong.
raw_matrix_list = [[1, 0, 1, 0, 1, 0],
[1, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 1]]
def rotate_matrix_list(raw_matrix_list):
rows = len(raw_matrix_list)
cols = len(raw_matrix_list[0])
new_matrix_list = [[0] * rows] * cols
for ii in xrange(cols):
for jj in xrange(rows):
# print str(ii) + ', ' + str(jj) + ', ' + str(rows)
new_matrix_list[ii][jj] = raw_matrix_list[rows-jj - 1][ii]
return(new_matrix_list)
rotate_matrix_list(raw_matrix_list)
The result I get is
[[1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0]]
What I want to get is:
[[1, 0, 1, 1], [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 1], [1, 1, 0, 0]]
===
$ python --version
Python 2.7.12 :: Anaconda 2.3.0 (x86_64)
===
update 2
Now I got the answer of how to do it in python with zip function. But I just failed to see why my code did not work.
Well, doing a transpose with vanilla lists in Python is pretty easy: use zip and the splat operator:
>>> raw_matrix_list = [[1, 0, 1, 0, 1, 0],
... [1, 0, 0, 0, 1, 0],
... [0, 0, 0, 0, 0, 1],
... [1, 0, 0, 0, 1, 1]]
>>> transpose = list(zip(*raw_matrix_list))
>>> transpose
[(1, 1, 0, 1), (0, 0, 0, 0), (1, 0, 0, 0), (0, 0, 0, 0), (1, 1, 0, 1), (0, 0, 1, 1)]
>>> from pprint import pprint
>>> pprint(transpose)
[(1, 1, 0, 1),
(0, 0, 0, 0),
(1, 0, 0, 0),
(0, 0, 0, 0),
(1, 1, 0, 1),
(0, 0, 1, 1)]
For python 2, you only need zip(*raw_matrix_list)) rather than list(zip(*raw_matrix_list)))
If a list of tuples won't do:
>>> transpose = [list(t) for t in zip(*raw_matrix_list)]
>>> pprint(transpose)
[[1, 1, 0, 1],
[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[1, 1, 0, 1],
[0, 0, 1, 1]]
The problem with your solution is that you use:
new_matrix_list = [[0] * rows] * cols
This makes every list the same object.
See this example for the problem:
>>> x = [[0]*3] * 4
>>> x
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> x[0][0] = 1
>>> x
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
Use something like:
new_matrix_list = [[0 for _ in range(rows)] for _ in range(cols)]
And you should be well on your way.
Using a nested list comprehension:
rows, cols = len(raw_matrix_list), len(raw_matrix_list[0])
>>> [[raw_matrix_list[i][j] for i in range(rows)] for j in range(cols)]
[[1, 1, 0, 1],
[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[1, 1, 0, 1],
[0, 0, 1, 1]]
There are already answers that help solve your problem. As to why your code doesn't work, shouldn't it be this (by definition of matrix transpose):
new_matrix_list[ii][jj] = raw_matrix_list[jj][ii]