У меня есть датафрейм, который выглядит так:
df = pd.DataFrame({'ID': [4]*2 +[5]*4 , 'Timestamp' : pd.date_range('2000-01-01', periods=6)})
ID Timestamp
0 4 2000-01-01
1 4 2000-01-02
2 5 2000-01-03
3 5 2000-01-04
4 5 2000-01-05
5 5 2000-01-06
Я хочу, чтобы последняя запись в столбце идентификатора была идентифицирована (помечена как 0). Таким образом, желаемый результат должен быть примерно таким:
ID Timestamp last
0 4 2000-01-01 -
1 4 2000-01-02 0
2 5 2000-01-03 -
3 5 2000-01-04 -
4 5 2000-01-05 -
5 5 2000-01-06 0
Как я могу это сделать? Я пробовал использовать различные опции df.duplicated('ID'), но с этим я могу удалить последнюю запись, но не идентифицировать/пометить последнюю запись
Добавьте параметр keep='last'
для mask
возврата с True
для не последних значений и False
для последних значений:
df['last'] = np.where(df.duplicated('ID', keep='last'), '-', '0')
print (df)
ID Timestamp last
0 4 2000-01-01 -
1 4 2000-01-02 0
2 5 2000-01-03 -
3 5 2000-01-04 -
4 5 2000-01-05 -
5 5 2000-01-06 0
Деталь:
print (df.duplicated('ID', keep='last'))
0 True
1 False
2 True
3 True
4 True
5 False
dtype: bool
Ты можешь сделать:
df.loc[np.flatnonzero(df.ID != df.ID.shift(-1)), 'last'] = 0
df.fillna('-')
ID Timestamp last
0 4 2000-01-01 -
1 4 2000-01-02 0
2 5 2000-01-03 -
3 5 2000-01-04 -
4 5 2000-01-05 -
5 5 2000-01-06 0
Где сравнение df
со сдвинутой версией самого себя ( pd.shift
):
df.ID != df.ID.shift(-1)
0 False
1 True
2 False
3 False
4 False
5 True
Name: ID, dtype: bool
np.flatnonzero
True
в последней позиции для каждого ID
, а np.flatnonzero
даст вам позицию True
s:
np.flatnonzero(df.ID != df.ID.shift(-1))
#array([1, 5], dtype=int64)
Наконец, используйте .loc
чтобы установить last
на ноль в этих позициях.
Используя GroupBy.tail
:
df.loc[df.groupby('ID').tail(1).index, 'last'] = 0
print(df)
# ID Timestamp last
# 0 4 2000-01-01 NaN
# 1 4 2000-01-02 0.0
# 2 5 2000-01-03 NaN
# 3 5 2000-01-04 NaN
# 4 5 2000-01-05 NaN
# 5 5 2000-01-06 0.0