Home > front end >  Python - Replacing Values Leading Up To 1s in an Array
Python - Replacing Values Leading Up To 1s in an Array

Time:01-20

Pretend I have a pandas Series that consists of 0s and 1s, but this can work with numpy arrays or any iterable. I would like to create a formula that would take an array and an input n and then return a new series that contains 1s at the nth indices leading up to every time that there is at least a single 1 in the original series. Here is an example:

array = np.array([0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1])

> preceding_indices_function(array, 2)
np.array([0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1])

For each time there is a 1 in the input array, the two indices preceding it are filled in with 1 regardless of whether there is a 0 or 1 in that index in the original array.

I would really appreciate some help on this. Thanks!

CodePudding user response:

Use a convolution with np.convolve:

N = 2

# craft a custom kernel
kernel = np.ones(2*N 1)
kernel[-N:] = 0
# array([1, 1, 1, 0, 0])

out = (np.convolve(array, kernel, mode='same') != 0).astype(int)

Output:

array([0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1])

CodePudding user response:

Unless you don't want to use numpy, mozway's transpose is the best solution.

But since several iterations have been given, I add my itertools based solution

[a or b or c for a,b,c in itertools.zip_longest(array, array[1:], array[2:], fillvalue=0)]

zip_longest is the same as classical zip, but if the iterators have different "lengths", the number of iteration is the one of the longest, and finished iterators will return None. Unless you add a fillvalue parameter to zip_longest.

So, here itertools.zip_longest(array, array[1:], array[2:], fillvalue=0) gives a sequence of triplets (a,b,c), of 3 subsequent elements (a being the current element, b the next, c the one after, b and c being 0 if there isn't any next element or element after the next).

So from there, a simple comprehension build a list of [a or b or c] that is 1 if a, or b or c is 1, 0 else.

CodePudding user response:

import numpy as np

array = np.array([0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1])

array = np.array([a or array[idx 1] or array[idx 2] for idx, a in enumerate(array[:-2])]   [array[-2] or array[-1]]   [array[-1]])

CodePudding user response:

this function works if a is a list, should work with other iterables as well:

def preceding_indices_function(array, n):
  for i in range(len(a)):
    if array[i] == 1:
      for j in range(n):
        if i-j-1 >= 0:
          array[i-j-1] = 1
  return array

CodePudding user response:

I got a solution that is similar to the other one but slightly simpler in my opinion:

>>> [1 if (array[i 1] == 1 or array[i 2] == 1) else x for i,x in enumerate(array) if i < len(array) - 2]
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1]
  • Related