Вот один подход, использующий lambda
с DataFrame.groupby
и DataFrame.apply
:
f = lambda x: (x.ne(x.shift()) & x.shift().notna()).astype(int)
df['Flipped'] = df.groupby('DISTRICT')['DOMINANT_PARTY'].apply(f).values
Обновление - Объяснение
lambda
здесь является сокращением для функции
def flipped(x):
return x.ne(x.shift()) & x.shift().notna()
Функция принимает Series
- в данном случае ['DOMINANT_PARTY']
.
Давайте посмотрим на район, где есть«перевернуть», чтобы объяснить (Район 19):
DISTRICT Year DOMINANT_PARTY ...
90 19 2014 REP ...
91 19 2015 REP ...
92 19 2016 DEM ...
93 19 2017 DEM ...
94 19 2018 DEM ...
Здесь наша x
с примененной функцией - это Серии:
90 REP
91 REP
92 DEM
93 DEM
94 DEM
и x.shift()
:
90 NaN
91 REP
92 REP
93 DEM
94 DEM
Первое логическое выражение в функции f
сравнивает эти ряды с методом Series.ne
(не равным), который будет:
90 REP != NaN True
91 REP != REP False
92 DEM != REP True
93 DEM != DEM False
94 DEM != DEM False
Обратите внимание, как мыиметь 2 True
значений, так как первая строка - 'REP' действительно не равна NaN.Вот почему у нас есть второе логическое выражение для удовлетворения x.shift()
НЕ равно NaN
(x.shift().notna()
).Оператор &
является логическим оператором AND, требующим выполнения обоих этих условий.
90 REP != NaN False
91 REP != REP False
92 DEM != REP True
93 DEM != DEM False
94 DEM != DEM False