Я разработал другое решение вашего вопроса, основанное на группировке и использовании горячего кодирования (get_dummy
).
Вот код:
df = pd.DataFrame({'B': ['X', 'X' , 'Y', 'X', 'Y', 'Y', 'X', 'X', 'Y', 'Y', 'X', 'Y'],
'group': ["IT", "IT", "IT", "MV", "MV", "MV", "IT", "MV", "MV", "IT", "IT", "MV"]})
# add a one-hot encoding to the dataframe.
t = pd.concat([df, pd.get_dummies(df.B)], axis=1)
t.index.name = "inx"
# do a rolling sum of 4. It's the past 3, plus 1.
t = t.groupby("group").rolling(4, min_periods = 1).sum()
t = t.reset_index().set_index("inx").sort_index()
# remove the extra '1' from the rolling result.
t.loc[:, ["X", "Y"]] = t.loc[:, ["X", "Y"]] - 1
# merge back the results with the original dataframe.
t = pd.concat([df, t[["X", "Y"]]], axis=1)
# create a 'count' column which is based on the values of 'B'.
t["count"] = t.lookup(t.index, t.B )
Результат:
B group X Y count
inx
0 X IT 0.0 -1.0 0.0
1 X IT 1.0 -1.0 1.0
2 Y IT 1.0 0.0 0.0
3 X MV 0.0 -1.0 0.0
4 Y MV 0.0 0.0 0.0
5 Y MV 0.0 1.0 1.0
6 X IT 2.0 0.0 2.0
7 X MV 1.0 1.0 1.0
8 Y MV 0.0 2.0 2.0
9 Y IT 1.0 1.0 1.0
10 X IT 1.0 1.0 1.0
11 Y MV 0.0 2.0 2.0
Все в одной строке:
df['count'] = (pd.concat([df, df['B'].str.get_dummies()], axis=1)
.groupby('group')
.rolling(4, min_periods=1)
.sum()
.sort_index(level=1)
.reset_index(drop=True)
.lookup(df.index, df['B']) - 1)