I am dealing with a dataset with strings in a column, and I need to count the number of changes in the data frame for that column. So if the data frame were grouped by column 'id', one group instance would look like the example below:
id vehicle
'abc' 'bmw'
'abc' 'bmw'
'abc' 'yamaha'
'abc' 'suzuki'
'abc' 'suzuki'
'abc' 'kawasaki'
So in this case, I would like to be able to say that id 'abc' changed vehicle brand 3 times. Is there an efficient way to do this over multiple groups for column 'id'?
I can think of 2 ways:
1) groupby on 'id' and call apply on the 'vehicle' column and pass method nunique, you have to subtract 1 as you are looking for changes rather than just an overall unique count:
In [292]:
df.groupby('id')['vehicle'].nunique() -1
Out[292]:
id
'abc' 3
Name: vehicle, dtype: int64
2) apply a lambda that tests whether the current vehicle does not equal the previous vehicle using shift, this is more semantically correct as this detects changes rather than just the overall unique count, calling sum on booleans will convert True and False to 1 and 0 respectively:
In [293]:
df.groupby('id')['vehicle'].apply(lambda x: x != x.shift()).sum() - 1
Out[293]:
3
The -1 is required on the above as for the first row it will compare with a row that doesn't exist and comparisons with NaN don't make sense in this case see below:
In [301]:
df.groupby('id')['vehicle'].apply(lambda x: x != x.shift())
Out[301]:
0 True
1 False
2 True
3 True
4 False
5 True
Name: 'abc', dtype: bool
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With