6

I have a list that looks like:

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

I need to append to a list, the index when the element changes from 0 to 1 (and not from 1 to 0).

I've tried to do the following, but it also registers when it changes from 1 to 0.

i = 0 
while i != len(mot)-1:
    if mot[i] != mot[i+1]:
        mot_daily_index.append(i)
    i += 1

Also, but not as important, is there a cleaner implementation?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
hcp
  • 319
  • 2
  • 16

8 Answers8

15

Here is how you can do that with a list comprehension:

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]
mot_daily_index = [i for i,m in enumerate(mot) if i and m and not mot[i-1]]
print(mot_daily_index)

Output:

[7, 24]

Explanation:

  • list(enumerate([7,5,9,3])) will return [(0, 7), (1, 5), (2, 9), (3, 3)], so the i in i for i, m in enumerate, is the index of m during that iteration.
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Red
  • 26,798
  • 7
  • 36
  • 58
6

Use a list comprehension with a filter to get your indexes:

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

idx = [i for i,v in enumerate(mot) if i and v > mot[i-1]]
print(idx)

Output:

[7, 24]
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
5

You could use

lst = [0, 0, 0, 1, 1, 1, 0, 1]
#      0  1  2  3  4  5  6  7

for index, (x, y) in enumerate(zip(lst, lst[1:])):
    if x == 0 and y == 1:
        print("Changed from 0 to 1 at", index)

Which yields

Changed from 0 to 1 at 2
Changed from 0 to 1 at 6
Jan
  • 42,290
  • 8
  • 54
  • 79
5

Here's a solution using itertools.groupby to group the list into 0's and 1's:

from itertools import groupby

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

mot_daily_index = []
l = 0
for s, g in groupby(mot):
    if s == 1:
        mot_daily_index.append(l)
    l += len(list(g))

print(mot_daily_index)

Output:

[7, 24]
Nick
  • 138,499
  • 22
  • 57
  • 95
4
mot = [0,0,0,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0]
mot_daily_index = [] # the required list
for i in range(len(a)-1):
    if a[i]==0 and a[i+1]==1:
        ind.append(i)

your code adds index whenever ith element is different from (i+1)th element

Atharva Kadlag
  • 302
  • 3
  • 15
2
  • For a 3M element container, this answer is 67.2 times faster than the accepted answer.
  • This can be accomplished with numpy, by converting the list to a numpy.array.
  • The code for his answer, is a modification of the code from Find index where elements change value numpy.
    • That question wanted all transitions v[:-1] != v[1:], not just the small to large transitions, v[:-1] < v[1:], in this question.
  • Create a Boolean array, by comparing the array to itself, shifted by one place.
  • Use np.where to return the indices for True
    • This finds the index before the change, because the arrays are shifted for comparison, so use +1 to get the correct value.
import numpy as np

v = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]

# convert to array
v = np.array(v)

# create a Boolean array
map_ = v[:-1] < v[1:]

# return the indices
idx = np.where(map_)[0] + 1

print(idx)
[out]:
array([ 7, 24], dtype=int64)

%timeit

# v is 3M elements
v = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0] * 100000

# accepted answer
%timeit [i for i,m in enumerate(v) if i and m and not v[i-1]]
[out]:
336 ms ± 14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# this answer
v = np.array(v)
%timeit np.where(v[:-1] < v[1:])[0] + 1
[out]:
5.03 ms ± 85.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
1

A oneliner using zip:

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

[i+1 for i,m in enumerate(zip(mot[:-1],mot[1:])) if m[0]<m[1]]

# [7, 24]
AnsFourtyTwo
  • 2,480
  • 2
  • 13
  • 33
1

Another list comprehension take:

mot = [0,1,1,1,1,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0]

change_mot = [index+1 for index, value in enumerate(zip(mot[:-1], mot[1:], )) if value[1] - value[0] == 1]

Which yields

[1, 8, 11, 15]

This picks up the increase and records the index only if the increase = 1.

Kristin H
  • 359
  • 2
  • 12