Pandas: Calculate for how much time a value is consecutive

Question:

I’m starting from a panads df that looks like this:

value  time  button
 10    1000   up
 8     1100   up
 4     1150   down
 1     1200   down
 6     1225   up
 5     1300   no
 5     1350   no

What I need is calculated for how long the button up or the button down were pressed

Basically don’t do anything until there are consicutive "up" or "down" or "no", but when they change I need to substract from the last occurence the first one and store the results in a new df to end with something like this:

button  time
up       100
down     100
up       25
no       125

I’ve tried to do so with this:


df['same_as_prev'] = (df['button'] == df['button'].shift()).astype(int)


df['consec_rows'] = df['same_as_prev'].cumsum()


df_result = df.groupby(['button','consec_rows']).agg({'time': lambda x: x.iloc[-1]-x.iloc[0]})

But I’m always getting 0 as results

Asked By: itt

||

Answers:

You can use:

# set up grouper (consecutive values)
group = df['button'].ne(df['button'].shift()).cumsum()

# aggregate
out = (df.assign(time=df['time'].diff())
         .groupby(group, group_keys=False)
         .agg({'button': 'first', 'time': 'sum'})
         .reset_index(drop=True)
      )

Output:

  button   time
0     up  100.0
1   down  100.0
2     up   25.0
3     no  125.0
Answered By: mozway

I would do the following:

import pandas as pd
df = pd.DataFrame({
    'value': [10, 8, 4, 1, 6, 5, 5],
    'time': [1000, 1100, 1150, 1200, 1225, 1300, 1350],
    'button': ['up', 'up', 'down', 'down', 'up', 'no', 'no'],
})
initial_time = df.time.values[0]
changes = df.mask(df.button == df.button.shift(-1)).dropna()
result = (
    changes[['button']]
    .assign(time=(
        changes.time - 
        changes.time.shift(fill_value=initial_time)
    ))
    .reset_index(drop=True)
    
)

output:

  button   time
0     up  100.0
1   down  100.0
2     up   25.0
3     no  125.0
Answered By: Zach Flanders
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.