How to smooth list of numerical values in Python? - python

I have a collection of lists of integer values in python like the following:
[0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]
Now I would like to have a somewhat "smoothed" sequence where each value with the same preceding and following value (which both differ from the central value in question) is replaced with this preceeding-following value. So my list above becomes:
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1]
(The order or procession is from left to right, just to reconcile possible conflicting groupings.)
How could I achieve list?
Bonus: same as above with possible parametrization how many preceeding-following values must occur to change the central value (2-2 or 3-3 instead of just 1-1).

A straightforward loop should do the trick:
_list = [0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]
for i in range(1, len(_list)-1):
if _list[i-1] == _list[i+1]:
_list[i] = _list[i-1]
print(_list)
Output:
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1]

arr = [0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]
res = [arr[0]]
i = 0
for i in range(1,len(arr)):
if res[i-1] not in arr[i:i+2]:
res.append(arr[i])
else:
res.append(res[i-1] )
print(res)

To allow the number of preceding / following values to be changed, you can create a 'pad' the list and iterate through a moving window on the padded list to check if all surrounding values are the same.
def smooth(lst, values=1, padding=None):
padded = [padding] * values + lst + [padding] * values
for i, n in enumerate(lst):
surrounding = set(padded[i:i+values] + padded[i+values+1:i+values*2+1])
if len(surrounding) == 1:
yield surrounding.pop()
else:
yield n
print(list(smooth([0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]))) # [0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1]
If your input list may contain None, choose a different padding parameter when calling the generator.

Related

Is there a function I can use in Python to randomly select elements equal to specified number and change it to another?

For instance, if I have the following distribution, I want to randomly select 4 elements = 1 and change that element to = 0.
lst = [1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0]
-> Function <-
lst = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0]
or
lst = [1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
or
lst = [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]
or ....
Using numpy:
ones = np.where(lst)[0]
to_zero = np.random.choice(ones, 4, replace=False)
for i in to_zero: # Alternatively, if lst is an array: lst[to_zero] = 0
lst[i] = 0
To achieve what you want, you first need to get the list of the indexes of the one elements. Then you need to pick 4 random indexes and update the values from the starting list.
Note that you cannot use the random.choices method because it doesn’t return unique values, use random.sample instead.
def update_randomly(tab):
n = range(len(tab))
one_indexes = [i for i in n if tab[i] == 1]
rdm_indexes = random.sample(one_indexes, 4)
return [0 if i in rdm_indexes else tab[i] for i in n]

Program corresponding to Complete Boolean Lattice *Q_n*

I am first year student of Math faculty, and I didn't have programming class yet.
I am working on a project and to simplify my calculations it would be nice to implement a program that would calculate a matrix corresponding to the complete boolean lattice Q_n, which is a set of n integers from 1 to n and all of its possible subsets.
For example, when n=4 the matrix would be the following:
1;0;0;0;1;1;1;0;0;0;1;1;1;0;1
0;1;0;0;1;0;0;1;1;0;1;1;0;1;1
0;0;1;0;0;1;0;1;0;1;1;0;1;1;1
0;0;0;1;0;0;1;0;1;1;0;1;1;1;1
where first column correspond to the subset {1} of {1,2,3,4}, second column to subset {2} of {1,2,3,4}, column 5 for example to subset {1,2} of {1,2,3,4} and so on.
My idea was to create first all zero matrix of the corresponding size and then I do not know how to proceed. Please help me to get ideas.
The itertools module makes this easy. Here is one way:
import itertools
def subset_matrix(n):
A = [[0]*pow(2,n) for _ in range(n)]
j = 0
for k in range(n+1):
for c in itertools.combinations(range(n),k):
for i in c:
A[i][j] = 1
j += 1
return A
#for example:
A = subset_matrix(4)
for row in A:
print(row)
Output:
[0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1]
[0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1]
[0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1]
[0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1]

How can I generate a list of lists of permutations

Let's say I have a list of pattern [2, 1] and given a length = 5.
The pattern means that there are sets of 2 and 1 'ones' in the list in that order in a list of length = 5.
Also the space or 0 between successive groups has to be at least one.
What I've tried is:
for curr_col in pattern_list:
curr_pattern = curr_col
example_combo = [0] * dim0
idx, group_strt_idxs = 0, []
for num in curr_pattern :
group_strt_idxs.append(idx)
for i in range(num ):
example_combo[idx] = 1
idx += 1
if idx < dim0 and dim0 > 1:
example_combo[idx] = 0
idx += 1
print('ex', example_combo)
Please help!
The problem is to put the zeros into len(constraints_list) + 1 buckets. The first and last one can contain 0 or more zeros, the intermediate ones must contain at least one.
We generate the possible repartitions in the repartitions function. It is then easy to build the corresponding list:
from itertools import zip_longest
def repartitions(number, buckets, start=None):
if start is None:
start = []
mini = 0 # first sequence of zeros can be empty
else:
mini = 1 # others contain at least one zero
if buckets == 1:
# last bucket, we put all remaining zeros here
start = start + [number]
yield start
else:
for i in range(mini, number-buckets+3):
# we have to keep at least 1 zero for each other bucket
# except the last one.
current = start + [i]
yield from repartitions(number-i, buckets-1, current)
def permutations_with_constraints(constraints_list, length):
number_of_zeros = length - sum(constraints_list)
buckets = len(constraints_list) + 1
for rep in repartitions(number_of_zeros, buckets):
out = sum(([0]*zeros + [1]*ones
for zeros, ones in zip_longest(rep, constraints_list, fillvalue=0)), [])
yield out
Some examples:
print(list(permutations_with_constraints([1, 2], 5)))
# [[1, 0, 1, 1, 0], [1, 0, 0, 1, 1], [0, 1, 0, 1, 1]]
print(list(permutations_with_constraints([2, 3, 2], 11)))
# [[1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0],
# [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0],
# [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],
# [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0],
# [1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1],
# [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],
# [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0],
# [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1],
# [0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1],
# [0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1]]
Some explanations about the sum, as you asked in comments:
We have a rep list, and a one item shorter constraints list. We zip them with zip_longest and a fillvalue=0, which gives us [(rep[0], constraints[0]), (rep[1], constraints[1]), ... (rep[-1], 0)]. (It's really a generator, not a list, but this doesn't change anything to the explanation). The last 0 fills the missing value in constraints.
We then build a list from each tuple. For example, (2, 3) will give us [0, 0, 1, 1, 1]. sum then adds these lists, using [] as a start value.
Since the length of the groups of 1's are already given, the recursion can determine the placing for each:
def generate_groups(d, fill=1):
return [[fill]*i for i in d]
def all_groups(_d, _len):
def groupings(d, current = []):
if sum(not i for i in current) == d and sum(i == '*' for i in current) == len(_d):
yield current
else:
if sum(not i for i in current) < d:
yield from groupings(d, current+[0])
if not current or not current[-1]:
yield from groupings(d, current+['*'])
return [(lambda x, y:[c for h in y for c in ([h] if not h else next(x))])(iter(generate_groups(_d)), i)
for i in groupings(_len-sum(_d))]
print(all_groups([2, 1], 5))
print(all_groups([2, 3, 2], 11))
Output:
[[0, 1, 1, 0, 1], [1, 1, 0, 0, 1], [1, 1, 0, 1, 0]]
[[0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1], [0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0]]

Create Python List using a True/False expression check? [duplicate]

This question already has answers here:
Inconsistent comprehension syntax?
(3 answers)
Closed 7 years ago.
Looking to generate a Python list that uses an if statement to check whether a number is even or odd. If even take the List value as '1' and if odd take the list value as '0'.
Progress to date:
List1 = [x for x in range(0,99) if x % 2 == 0]
However, this only generates a list of even numbers. When I change the expression to add an else check I get a syntax error. Any help appreciated.
List1 = [1 for x in range(0,99) if x % 2 == 0 else 0]
You are using a filter, where you want to alter the left-hand-side expression instead, using a conditional expression:
[1 if x % 2 == 0 else 0 for x in range(99)]
This can be simplified to:
[1 - (x % 2) for x in range(99)]
Change the if else condition present inside the list_comprehension like below.
>>> [1 if x % 2 == 0 else 0 for x in range(0,99)]
[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, 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]
This would print 1 for even numbers and 0 for odd numbers.

Count occurrences of number in two lists and return one list

I am trying to count the number of occurrences a 0 occurs in two lists together and save that number using python. I am trying to put it into a third list using 'list comprehension' commands but I am not getting the output I want.
My two lists are:
list1 = [0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1]
list2 = [0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0]
So, anytime there is a 0 occuring in the same place in each list I would like to append '0' into a new list. I would like to do the same thing with the ones.
the new list should look like:
newlist = [0,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1]
Thanks for the help in advance, I've been trying to figure out how to do this for several hours now to no avail!
You can use a list comprehension, like this:
answer = [x for x, y in zip(list1, list2) if x == y]
Alternatively, you can solve it without list comprehensions by using simple list operations:
answer = []
for x, y in zip(list1, list2):
if x == y:
answer.append(x)
In both cases, answerwill be:
[0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[x or y for x,y zip(list1, list2)]
[0 if x == (0,0) else 1 for x in zip(list1,list2)]
list1 = [0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1]
list2 = [0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0]
temp = [ list1[i] if list1[i] == list2[i] else 2 for i in range( 0, len(list1) )]
answer = [value for value in temp if value != 2]
print( answer )
Solution
If you want list consisting of 0 and 1 in order of 0 or 1 appearing at the same position in both lists, then you can use the following list comprehension:
result = [a for a, b in zip(list1, list2) if a==b]
Test
Testing your values however:
>>> newlist = [a for a, b in zip(list1, list2) if a==b]
>>> newlist
[0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
you see that the result is not equal to what you have been expecting:
>>> newlist == [0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
False
So the question for you is: is the expected result you have provided a correct one?

Categories