I use Python with numpy.
I have numpy array b:
b = np.array([True,True,True,False,False,True,True,False,False,False,True,False,True])
I need to replace arrays [False] and [False,False] on arrays [True] and [True,True] respectively.
(I need to exclude single and double saltuses of an array in False)
For this exsample:
out= np.array([True,True,True,True, True, True,True,False,False,False,True,True,True])
Can someone please suggest, how do I get out?
P.S: if I need to replace arrays [False],[False,False], [False,False,False] and [False,False,False,False] on arrays [True],[True,True], [True,True,True] and [True,True,True,True] respectively?
How about use scipy.ndimage.binary_dilation & scipy.ndimage.binary_erosion
import numpy as np
from scipy import ndimage
b = np.array([True,True,True,False,False,True,True,False,False,False,True,False,True])
ndimage.binary_erosion(ndimage.binary_dilation(b), border_value=1)
This is may not be the best way to solve this but have a look at the following ...
In [115]: b
Out[115]:
array([ True, True, True, False, False, True, True, False, False,
False, True, False, True], dtype=bool)
In [116]: l = [(k,len(list(g))) for k, g in itertools.groupby(b)]
In [117]: l
Out[117]:
[(True, 3),
(False, 2),
(True, 2),
(False, 3),
(True, 1),
(False, 1),
(True, 1)]
In [118]: l2 = [(True, x[1]) if x[1] in [1,2] else x for x in l]
In [119]: l2
Out[119]: [(True, 3), (True, 2), (True, 2), (False, 3), (True, 1), (True, 1), (True, 1)]
In [120]: l3 = [[x[0]] * x[1] for x in l2]
In [121]: l3
Out[121]:
[[True, True, True],
[True, True],
[True, True],
[False, False, False],
[True],
[True],
[True]]
In [122]: l4 = [x for x in itertools.chain(*l3)]
In [123]: l4
Out[123]:
[True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
True,
True,
True]
In [124]: out = np.array(l4)
In [125]: out
Out[125]:
array([ True, True, True, True, True, True, True, False, False,
False, True, True, True], dtype=bool)
I haven't numpy installed, but I think the following code will give you idea to do something similar in numpy, if I understood correctly what you want:
b = [True,True,True,False,False,True,True,False,False,False,True,False,True,
False,False,False,False,True,False,False,True]
print b,'\n'
def grignote(X):
it = iter(xrange(len(X)))
for i in it:
print 'i == %d %s' % (i,X[i])
if X[i]==False:
j = (k for k in it if X[k]==True).next()
print ' j == %d %s X[%d:%d]==%r' % (j,X[j],i,j,X[i:j])
if j-i<3:
print ' executing X[%d:%d]==%r' % (i,j,[True for m in xrange(j-i)])
X[i:j] = [True for m in xrange(j-i)]
else:
print ' --- no execution --- too long'
grignote(b)
print '\n',b
result
[True, True, True, False, False, True, True, False, False, False, True, False, True, False, False, False, False, True, False, False, True]
i == 0 True
i == 1 True
i == 2 True
i == 3 False
j == 5 True X[3:5]==[False, False]
executing X[3:5]==[True, True]
i == 6 True
i == 7 False
j == 10 True X[7:10]==[False, False, False]
--- no execution --- too long
i == 11 False
j == 12 True X[11:12]==[False]
executing X[11:12]==[True]
i == 13 False
j == 17 True X[13:17]==[False, False, False, False]
--- no execution --- too long
i == 18 False
j == 20 True X[18:20]==[False, False]
executing X[18:20]==[True, True]
[True, True, True, True, True, True, True, False, False, False, True, True, True, False, False, False, False, True, True, True, True]
Related
How to compare values in val against arr based on operators o?
import numpy as np
from operator import gt, lt
val = np.array([[3,7,1], [4,8,5], [5,10,3]])
arr = np.array([[1,2,3,4,5], [6,7,8,9,10], [9,7,5,3,1]])
o = (gt, gt, lt)
# [3,7,1]
# (3 gt [1,2,3,4,5]) & (7 gt [6,7,8,9,10] & (1 lt [9,7,5,3,1])
# [True, True, False, False, False] & [True, False, False, False, False] & [True, True, True, True, False]
# => [True, False, False, False, False]
# [4,8,5]
# (4 gt [1,2,3,4,5]) & (8 gt [6,7,8,9,10] & (5 lt [9,7,5,3,1])
# => [True, True, False, False, False]
# [5,10,3]
# (5 gt [1,2,3,4,5]) & (10 gt [6,7,8,9,10]) & (3 lt [9,7,5,3,1])
# => [True, True, True, False, False]
result = np.array([[True, False, False, False, False],
[True, True, False, False, False],
[True, True, True, False, False]])
For each val_i, operator o_j is applied between val_i_j and all elements in arr_j. The resulting vectors are compared with __rand__.
Current solution seems too difficult.
out = []
for i in range(len(val)):
m = o[0](val[i][0], arr[0])
print(val[i][0], m)
for j in range(len(o)):
if j > 0:
m &= o[j](val[i][j], arr[j])
print(val[i][j], m)
out.append(list(mask))
You can try this:
import numpy as np
val = np.array([[3,7,1], [4,8,5], [5,10,3]])
arr = np.array([[1,2,3,4,5], [6,7,8,9,10], [9,7,5,3,1]])
o = (np.greater, np.greater, np.less)
out = np.logical_and.reduce([o[i](val[:, i, None], arr[i]) for i in range(len(o))])
print(out)
It gives:
[[ True False False False False]
[ True True False False False]
[ True True True False False]]
X = np.arange(1, 26).reshape(5, 5)
X[:,1:2] % 2 == 0
The conditions should only be applied to the second column
I want the whole matrix where the condition is true like
[array([[False, True, False, False, False],
[ False, False, False, False, False],
[False, True, False, False, False],
[ False, False, False, False, False],
[False, True, False, False, False]])]
It's giving the error
IndexError: boolean index did not match indexed array along dimension 1; dimension is 5 but corresponding boolean dimension is 1
Is this what you want?
import numpy as np
X = np.arange(1, 26).reshape(5, 5)
X=[X[::] % 2 == 0]
print(X)
Output
[array([[False, True, False, True, False],
[ True, False, True, False, True],
[False, True, False, True, False],
[ True, False, True, False, True],
[False, True, False, True, False]])]
If you want to get the whole matrix where the condition is true. You can simply do this
X % 2 == 0
If you want to get the first column where condition is true then
X[:, 1:2] % 2 ==0
I have the following array:
[(True,False,True), (False,False,False), (False,False,True)]
If any element contains a True then they should all be true. So the above should become:
[(True,True,True), (False,False,False), (True,True,True)]
My below code attempts to do that but it simply converts all elements to True:
a = np.array([(True,False,True), (False,False,False), (False,True,False)], dtype='bool')
aint = a.astype('int')
print(aint)
aint[aint.sum() > 0] = (1,1,1)
print(aint.astype('bool'))
The output is:
[[1 0 1]
[0 0 0]
[0 1 0]]
[[ True True True]
[ True True True]
[ True True True]]
You could try np.any, which tests whether any array element along a given axis evaluates to True.
Here's a quick line of code that uses a list comprehension to get your intended result.
lst = [(True,False,True), (False,False,False), (False,False,True)]
result = [(np.any(x),) * len(x) for x in lst]
# result is [(True, True, True), (False, False, False), (True, True, True)]
I'm no numpy wizard but this should return what you want.
import numpy as np
def switch(arr):
if np.any(arr):
return np.ones(*arr.shape).astype(bool)
return arr.astype(bool)
np.apply_along_axis(switch, 1, a)
array([[ True, True, True],
[False, False, False],
[ True, True, True]])
ndarray.any along axis=1 and np.tile will get job done
np.tile(a.any(1)[:,None], a.shape[1])
array([[ True, True, True],
[False, False, False],
[ True, True, True]])
Create an array of True's based on the original array's second dimension and assign it to all rows that have a True in it.
>>> a
array([[ True, False, True],
[False, False, False],
[False, True, False]])
>>> a[a.any(1)] = np.ones(a.shape[1], dtype=bool)
>>> a
array([[ True, True, True],
[False, False, False],
[ True, True, True]])
>>>
Relies on Broadcasting.
This problem came up while trying to write code for a truth-table generating function.
How can I generate a list of lists of all length-n permutations of True and False? In other words, given a list of elements [True, False], how can I generate all permutations of all possible length-n combinations of those elements?
For example:
n=2 length-2 permutations are:
[[True, True], [True, False], [False, True], [False, False]]
n=3 the length-3 permutations are:
[[False, False, False],[False,False,True],
[False,True,False],[False,True,True],
[True,False,False],[True,False,True],[True,True,False],[True,True,True]]
I know there's 2^n lists in this list. I also have considered using itertools.product, but that only seems to give permutations of a specific combination. In this case, I think I want to generate permutations of ALL combinations of a length-n list of true/false.
Use itertools.product:
>>> import itertools
>>> l = [False, True]
>>> list(itertools.product(l, repeat=3))
[(False, False, False), (False, False, True), (False, True, False), (False, True, True), (True, False, False), (True, False, True), (True, True, False), (True, True, True)]
>>>
And if you want the to change the tuples inside the list to sublists, try a list comprehension:
>>> import itertools
>>> l = [False, True]
>>> [list(i) for i in itertools.product(l, repeat=3)]
[[False, False, False], [False, False, True], [False, True, False], [False, True, True], [True, False, False], [True, False, True], [True, True, False], [True, True, True]]
>>>
It's relatively easy if you consider the values to be bits instead. Like for the n = 3 case, see it as a value containing three bits.
Loop (using integers) from 0 to 2ⁿ - 1 (inclusive) and print all bits in each value (with 0 being False and 1 being True). Then you will have all permutations.
Of course, it's not a very Pythonic solution, but it's generic.
Try itertools.product with the repeat argument:
In [1]: from itertools import product
In [2]: product([True, False], repeat=2)
Out[2]: <itertools.product at 0x1c7eff51b40>
As you can see above, it returns an iterable, so wrap it in list():
In [3]: list(product([True, False], repeat=2))
Out[3]: [(True, True), (True, False), (False, True), (False, False)]
In [4]: list(product([True, False], repeat=3))
Out[4]:
[(True, True, True),
(True, True, False),
(True, False, True),
(True, False, False),
(False, True, True),
(False, True, False),
(False, False, True),
(False, False, False)]
In [5]: list(product([True, False], repeat=5))
Out[5]:
[(True, True, True, True, True),
(True, True, True, True, False),
(True, True, True, False, True),
(True, True, True, False, False),
(True, True, False, True, True),
...
It also returns a list of tuples instead of a list of lists, but that should be fine for most use cases and can be solved very easily with a list comprehension if lists are really needed:
[list(tup) for tup in mylist]
And if you want list of lists, not list of tuples, start with U9-Forward's answer:
import itertools
l=[False,True]
ll=list(itertools.product(l,repeat=3))
and continue:
lll=[]
for each in ll:
lll.append([EACH for EACH in each])
lll will be a list of lists, instead of tuples.
Much better way, following comments:
[list(elem) for elem in lll]
Thanks to Kevin.
It is not efficient solution but you can use:
def permuteBool(n, l):
... if n==0:
... return l
... return [permuteBool(n-1, l+[True])] + [permuteBool(n-1, l+[False])]
...
>>> permuteBool(3, [])
[[[[True, True, True], [True, True, False]], [[True, False, True], [True, False, False]]], [[[False, True, True], [False, True, False]], [[False, False, True], [False, False, False]]]]
EDIT: Looks like I didn't check the output before posting my answer. It'll stay as it is as the right way would be a duplicate answer of the correct answer.
Use this simple code:
>>> import itertools # library of magic
>>> length = 3 # length of your wanted permutations
>>> result = itertools.combinations( # combinations based on position
... [*[True, False] * length], # generates the items needed
... length # length of the wanted results
... )
>>> print([list(r) for in result])
[[False, False, False], [False, False, True], [False, True, False], [False, True, True], [True, False, False], [True, False, True], [True, True, False], [True, True, True]]
Here's a simple recursive list program
def list_exponential(n,set1=[]):
if n == 0:
print(set1)
else:
n-=1
list_exponential(n, [False]+set1)
list_exponential(n, [True]+set1)
list_exponential(5)
Sample output
$ python3 exponential.py 5
[False, False, False, False, False]
[True, False, False, False, False]
[False, True, False, False, False]
[True, True, False, False, False]
[False, False, True, False, False]
[True, False, True, False, False]
[False, True, True, False, False]
[True, True, True, False, False]
[False, False, False, True, False]
[True, False, False, True, False]
[False, True, False, True, False]
[True, True, False, True, False]
[False, False, True, True, False]
[True, False, True, True, False]
[False, True, True, True, False]
[True, True, True, True, False]
[False, False, False, False, True]
[True, False, False, False, True]
[False, True, False, False, True]
[True, True, False, False, True]
[False, False, True, False, True]
[True, False, True, False, True]
[False, True, True, False, True]
[True, True, True, False, True]
[False, False, False, True, True]
[True, False, False, True, True]
[False, True, False, True, True]
[True, True, False, True, True]
[False, False, True, True, True]
[True, False, True, True, True]
[False, True, True, True, True]
[True, True, True, True, True]
I have a boolean array and a want to convert that to an array, where only the last_n_trues True values are still True. A simple example:
>>> boolean_array = [False, False, True, True, True, False, False]
>>> last_n_trues = 2
>>> desired_output = [False, False, False, True, True, False, False]
My approach:
>>> import numpy as np
>>> idxs_of_trues = np.where(boolean_array)[0]
array([2, 3, 4], dtype=int64)
>>> idxs_of_trues_last_n = idxs_of_trues[-last_n_trues:]
array([3, 4], dtype=int64)
>>> [x in idxs_of_trues_last_n for x in range(0, len(boolean_array))]
[False, False, False, True, True, False, False]
Is there a faster way to do so? Especially the list comprehension seems pretty complicated to me...
You should just be able to simply use np.where
In [116]: x
Out[116]: array([False, False, True, True, True, False, False], dtype=bool)
In [117]: x[np.where(x)[0][:-2]] = False
In [118]: x
Out[118]: array([False, False, False, True, True, False, False], dtype=bool)
This just replaces all True that aren't the last 2 with False
This will only work if x is a np.array, so verify that before you try this.
Approach #1 : Here's one with cumsum -
def keep_lastNTrue_cumsum(a, n):
c = np.count_nonzero(a) # or a.sum()
a[c - a.cumsum() >= n] = 0
return a
Approach #2 : Two more with argpartition -
def keep_lastNTrue_argpartition1(a, n):
c = np.count_nonzero(a) # or a.sum()
a[np.sort(np.argpartition(a,-n)[-c:])[:-n]] = 0
return a
def keep_lastNTrue_argpartition2(a, n):
c = np.count_nonzero(a) # or a.sum()
p = np.argpartition(a,-n)[-a.sum():]
cn = c-n
idx = np.argpartition(p,cn)
a[p[idx[:cn]]] = 0
return a
Approach #3 : Another with a bit more of mask usage -
def keep_lastNTrue_allmask(a, n):
c = a.sum()
set_mask = np.ones(c, dtype=bool)
set_mask[:-n] = False
a[a] = set_mask
return a
Sample runs -
In [141]: boolean_array = np.array([False, False, True, True, True, False, False])
In [142]: keep_lastNTrue_cumsum(boolean_array, n=2)
Out[142]: array([False, False, False, True, True, False, False])
In [143]: boolean_array = np.array([False, False, True, True, True, False, False])
In [144]: keep_lastNTrue_argpartition1(boolean_array, n=2)
Out[144]: array([False, False, False, True, True, False, False])
In [145]: boolean_array = np.array([False, False, True, True, True, False, False])
In [146]: keep_lastNTrue_argpartition2(boolean_array, n=2)
Out[146]: array([False, False, False, True, True, False, False])
The fastest way without libraries is going to be to clone the list and iterate through it in reverse:
def foo(bools, last_n_trues):
result = bools[:]
count = 0
for i in range(len(bools) - 1, -1, -1):
if count < last_n_trues:
if result[i]:
count += 1
else:
result[i] = False
return result