Order of repetition per row and column in Python [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have been trying to figure the order of repetition per-row and just couldn't do it. Ok. Lets consider a ndarray of size (2, 11, 10)
a = np.array([
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 1, 1, 1, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 0, 0, 1, 0, 1, 1, 1, 0, 0],
[1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 0, 0, 1, 1],
[0, 1, 1, 1, 0, 0, 1, 1, 0, 1]
],
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 0, 0, 1, 0, 0],
[1, 1, 0, 1, 0, 1, 1, 1, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 1, 1, 0, 0],
[1, 0, 0, 0, 1, 1, 0, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 1, 1, 0, 1, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[1, 1, 1, 0, 0, 1, 1, 1, 0, 1]
]
])
What I wanted to is to get the order of every 1's per row based on a column. Whenever the first 1 is found in a row the order starts would start at 0; then goes to the second row if 1 is found here then the order is 1, but if the 1 is already present at the column index in the previous row, then it is ignored. For example
Lets consider these lists:
0 1 2 3 4 5 6 7 8 9 -> column index
0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], -> no 1's no order here
1 [1, 1, 0, 0, 0, 1, 1, 1, 0, 0], -> order starts at 0
2 [0, 1, 0, 0, 0, 1, 0, 0, 1, 0], -> order starts at 1
At row index 0 there are no 1 so nothing happens, at row index 1 there are ones in column index [0,1,5,6,7] this will be equal to 0; the output should be
column order
0 0
1 0
2 -
3 -
4 -
5 0
6 0
7 0
8 -
9 -
At row index 2 there are 1 at column index [1,5,8] whos order is 1; in there 1 and 5 are ignored because it already has an order 0 to it, but for the unknown order it should be 1; the final output should be
column order
0 0
1 0
2 -
3 -
4 -
5 0
6 0
7 0
8 1
9 -
I have tried using Numpy's np.where method to the index values; something like this
index = np.asarray(np.where(a == 1)).T
I have no idea what to do next. Can anyone please help me?

Apparently, the desired result--based on comments on the question and an earlier version of this answer--is to find the "dense ranking" of the row index of the first 1 in each column. (See the docstring of scipy.stats.rankdata for the meaning of "dense ranking".) The result can be found using a combination of the .argmax() method and scipy.stats.rankdata.
Here's a function that computes the order for a two-dimensional array. The question doesn't define what should happen when a column is all zeros; order assigns that column the value -1.
from scipy.stats import rankdata
def order(x):
result = x.argmax(axis=0)
result[(x == 0).all(axis=0)] = -1
rank = rankdata(result, method='dense') - 1 - np.any(result < 0)
return rank
For example, here is the array y:
In [71]: y
Out[71]:
array([[0, 1, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[1, 1, 1, 0, 1, 1, 0, 0],
[1, 0, 1, 1, 1, 1, 0, 0],
[1, 0, 0, 0, 1, 1, 1, 0]])
In [72]: order(y)
Out[72]: array([ 1, 0, 1, 2, 0, 0, 3, -1])
Here's the array a from the question:
In [73]: a
Out[73]:
array([[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 1, 1, 1, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 0, 0, 1, 0, 1, 1, 1, 0, 0],
[1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 0, 0, 1, 1],
[0, 1, 1, 1, 0, 0, 1, 1, 0, 1]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 0, 0, 1, 0, 0],
[1, 1, 0, 1, 0, 1, 1, 1, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 1, 1, 0, 0],
[1, 0, 0, 0, 1, 1, 0, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 1, 1, 0, 1, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[1, 1, 1, 0, 0, 1, 1, 1, 0, 1]]])
The function order() expects a two-dimensional array, so we must use a loop to get the order for each subarray in a:
In [74]: np.array([order(m) for m in a])
Out[74]:
array([[0, 0, 3, 3, 2, 0, 0, 0, 1, 4],
[2, 0, 3, 1, 0, 2, 2, 1, 0, 0]])

Related

Flatten arrays into a list of lists

I have this data structure:
[array([[0, 1, 0, 1, 1, 1, 0, 5, 1, 0, 2, 1]]), array([[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0],
[1, 3, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0]]), array([[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], etc....
I want to flatten this into a list of lists something like:
[[0 1 0 1 1 1 0 5 1 0 2 1]
[1 6 1 0 0 1 1 1 2 0 2 0]
[2 0 5 0 5 2 2 0 6 3 2 2]
[1 0 1 1 1 1 0 2 0 0 0 1]]
How do we do this in python?
I believe you're looking for vstack:
>>> np.vstack(l)
array([[0, 1, 0, 1, 1, 1, 0, 5, 1, 0, 2, 1],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0],
[1, 3, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
Note that this is equivalent to:
>>> np.concatenate(x, axis=0)
array([[0, 1, 0, 1, 1, 1, 0, 5, 1, 0, 2, 1],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0],
[1, 3, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
To convert to list, use tolist:
>>> np.vstack(l).tolist()
[[0, 1, 0, 1, 1, 1, 0, 5, 1, 0, 2, 1], [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0], [1, 3, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
# or
>>> np.concatenate(x, axis=0).tolist()
[[0, 1, 0, 1, 1, 1, 0, 5, 1, 0, 2, 1], [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0], [1, 3, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
Use flatten:
print([i.flatten() for i in l])
Or:
print(list(map(lambda x: x.flatten(),l)))
Both output:
[array([0, 1, 0, 1, 1, 1, 0, 5, 1, 0, 2, 1]), array([0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 1, 3, 1, 0, 0, 1, 1, 1, 1, 0, 1,
0]), array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0])]

Search through a 2-dimensional list without numpy

I'm looking to define a function that accepts two parameters: an int and a list.
If the function finds the integer in the list it returns its coordinates.
For example how would I do that for the number 4 in the following list, without using numpy?
l = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 1, 1, 0, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 1, 4, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
]
You can assume that the target will always show up only once and will always be contained in the list.
The target will always show up only once and will always be contained in the list
You can use enumerate to enumerate the outer lists and the elements of the inner lists.
def coords(lst, find):
return next((i, j) for i, sub in enumerate(lst)
for j, x in enumerate(sub)
if x == find)
Demo with your list l:
>>> coords(l, 2)
>>> (1, 1)
>>> coords(l, 1)
>>> (1, 2)
In case you later want to adapt the function to work properly if the target is not in the list, remember that next takes an optional default argument.
You can do something like this:
l = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 1, 1, 0, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 1, 4, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
]
def findElement(element, l):
for i in range(len(l)):
for j in range(len(l[i])):
if element==l[i][j]:
return (i,j)
return None
print(findElement(4,l))
Output:
(11, 7)
I would used solution like this:
#!/usr/bin/env ipython
# ---------------------
l = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 1, 1, 0, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 1, 4, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
]
# ----------------------------------
def search(value,listin):
coords = [[ival,kkval] for ival,dd in enumerate(listin) for kkval,val in enumerate(dd) if val==value]
return coords
# ----------------------------------
result = search(4,l)
print result
where I defined a function search, which can be used to search for certain value from an input list.
Here is my approach:
def matrix_search(target, matrix):
for row_index, row in enumerate(matrix):
try:
return (row_index, row.index(target))
except ValueError:
pass
raise ValueError('Target {} not found'.format(target))
Sample usage:
print(matrix_search(4, l))
Notes
To search a simple list, use the .index() method
The .index() method will either return the index of the element if found or throw a ValueError if not found. In our context, we just ignore this exception and move on to the next row.
At the end of the loop, we will throw an exception because the element is not found

Python: Remove sublist from a nested list following a criterion

I'm trying to remove sublists from a nested list containing all the possible permutation of [1, 1, 1, 0, 0, 0, 0]
[[0, 1, 0, 1, 0, 0, 1], [0, 1, 0, 0, 1, 1, 0], [0, 0, 1, 1, 0, 0, 1], [0, 0, 1, 1, 1, 0, 0], [0, 1, 1, 0, 0, 1, 0], [1, 0, 0, 0, 1, 1, 0], [0, 0, 1, 0, 0, 1, 1], [0, 0, 1, 0, 1, 1, 0], [0, 0, 1, 0, 1, 0, 1], [0, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0, 1], [1, 1, 0, 1, 0, 0, 0], [0, 1, 0, 1, 1, 0, 0], [1, 0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 0], [1, 1, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 1, 1], [1, 0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 1, 1, 0, 1], [0, 0, 0, 1, 1, 1, 0], [1, 0, 0, 0, 1, 0, 1], [1, 1, 1, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 1], [1, 0, 0, 1, 0, 1, 0], [1, 0, 0, 1, 0, 0, 1], [1, 1, 0, 0, 0, 0, 1], [1, 0, 1, 0, 0, 0, 1], [0, 0, 1, 1, 0, 1, 0]]
I want to remove all the sublists in which there are 3 consecutive 0 or two couples of consecutive 0 (eg. i want to remove [1, 0, 1, 0, 0, 0, 1] or [0, 0, 1, 1, 0, 0, 1]).
Can someone give me an advice on how to proceed? Thanks in advance!
You could define such a methode to find out if a given permutation p has those triple zeros or two double zeros:
def has_triple_zeros(p):
for i, e in enumerate(p[:-2]): # e are elements (0s and 1s) of the perm
if e == 0: # we encounter a 0
if p[i+1] == 0 and p[i+2] == 0: # the two following are also 0s
return True
return False # we made it to the end, no triple 0s
def has_two_double_zeros(p):
nb_doubles = 0
i = 0 # init loop
while i < len(p[:-1]):
if p[i] == 0: # we encounter a first 0
if p[i+1] == 0: # there is one next to it
nb_doubles += 1
i += 1 # skip the next element (already treated, cannot start new double)
i += 1 # increment the loop
return nb_doubles == 2
for p in lst: # here, lst is your list of permutations
print(p, has_two_double_zeros(p), has_triple_zeros(p))
Then just read your list of permutations and delete if it matches one of your criteria. This is an idea:
res = list() # result
for p in lst:
if not (has_two_double_zeros(p) or has_triple_zeros(p)):
res.append(p)
print(res)

How to get the length of repeated numbers column wise?

I am trying to get the length of repeated numbers in Python Numpy. For example, let's consider a simple ndarray
import numpy as np
a = np.array([
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 1, 0, 0, 1, 1, 1, 0, 1],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
])
The first column has [0, 1, 0, 1], the position of 1 is 1, now start counting from there, we get ones = 2 and zeros = 1. So I have to start counting ones and zeros when 1 is encountered (starting position).
so the answer for a would be
ones = [2, 2, 1, 1, 1, 3, 2, 2, 1, 1]
zeros = [1, 0, 2, 1, 0, 0, 1, 1, 1, 2]
Can any one please help me out?
Update
3D array:
a = np.array([
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 1, 1, 1, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
],
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 0, 0, 1, 0, 0],
[1, 1, 0, 1, 0, 1, 1, 1, 0, 0],
]
])
The expected output should be
ones = [
[2, 3, 0, 0, 1, 3, 2, 2, 1, 0],
[1, 3, 0, 2, 1, 1, 1, 2, 1, 1]
]
zeros = [
[1, 0, 0, 0, 0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 2, 0, 0, 0, 2, 2]
]
With focus on performance, here's one generic approach for ndarrays -
ones_count = a.sum(-2)
zeros_count = (a.shape[-2] - ones_count - a.argmax(-2))*a.any(-2)
One alternative to get zeros_count with selections using np.where, would be -
zeros_count = np.where(a.any(-2),a.shape[-2] - ones_count - a.argmax(-2),0)
Sample runs
2D case :
In [60]: a
Out[60]:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 1, 0, 0, 1, 1, 1, 0, 1],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 1, 1, 1, 1, 0, 0]])
In [61]: ones_count = a.sum(-2)
...: zeros_count = (a.shape[-2] - ones_count - a.argmax(-2))*a.any(-2)
...:
In [62]: ones_count
Out[62]: array([2, 2, 1, 1, 1, 3, 2, 2, 1, 1])
In [63]: zeros_count
Out[63]: array([1, 0, 2, 1, 0, 0, 1, 1, 1, 2])
3D case :
In [65]: a = np.array([
...: [
...: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
...: [1, 1, 0, 0, 0, 1, 1, 1, 0, 0],
...: [0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
...: [1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
...: ],
...: [
...: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
...: [0, 1, 0, 0, 1, 0, 0, 0, 1, 1],
...: [0, 1, 0, 1, 0, 0, 0, 1, 0, 0],
...: [1, 1, 0, 1, 0, 1, 1, 1, 0, 0],
...: ]
...: ])
In [66]: ones_count = a.sum(-2)
...: zeros_count = (a.shape[-2] - ones_count - a.argmax(-2))*a.any(-2)
...:
In [67]: ones_count
Out[67]:
array([[2, 3, 0, 0, 1, 3, 2, 2, 1, 0],
[1, 3, 0, 2, 1, 1, 1, 2, 1, 1]])
In [68]: zeros_count
Out[68]:
array([[1, 0, 0, 0, 0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 2, 0, 0, 0, 2, 2]])
and so on for higher dim arrays.

Append rows in array

I am making a Draughts game in python, I made an array 10 by 10 and I need to append values within the entire row so that is eventually looks like this;
(
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 0, 2, 0, 2, 0, 2, 0, 2],
[2, 0, 2, 0, 2, 0, 2, 0, 2, 0],
[0, 2, 0, 2, 0, 2, 0, 2, 0, 2],
[2, 0, 2, 0, 2, 0, 2, 0, 2, 0],
)
Here is my attempt at it so far, I know it's incorrect;
__author__ = 'Matt'
import array
Board_Array = array(10, 10)
pieces = ['Empty', 'White_Piece', 'Black_Piece', 'Upgraded_White_Piece', 'Upgraded_Black_Piece']
list(enumerate(pieces))
if Board_Array.array_equals == [1, 0]:
for i in range(10):
if (i%2) == 0:
array.pop([i])
array.insert(i,1)
You could use a nested list comprehension:
In [173]: [[((i+j) % 2)*k for i in range(10)] for k in (1,1,0,2,2)
for j in (0,1)]
Out[173]:
[[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 0, 2, 0, 2, 0, 2, 0, 2],
[2, 0, 2, 0, 2, 0, 2, 0, 2, 0],
[0, 2, 0, 2, 0, 2, 0, 2, 0, 2],
[2, 0, 2, 0, 2, 0, 2, 0, 2, 0]]
This is equivalent to
result = []
for k in (1,1,0,2,2):
for j in (0,1):
row = []
for i in range(10):
row.append(((i+j) % 2)*k)
result.append(row)

Categories