





Вы можете найти индекс первого 1 и установить для остальных 0:
mask = df['col2'].eq(1)
df.loc[mask & (df.index != mask.idxmax()), 'col2'] = 0
Для лучшей производительности см. Эффективно вернуть индекс первого значения, удовлетворяющего условию в массиве.
@timgeb, Для адаптации этого решения, думаю, можно использовать позиционную индексацию (вместо индексных меток). Что-то вроде df.loc[mask & (np.arange(df.shape[0]) != np.where(mask)[0][0]), 'col2'] = 0. Но я уверен, что есть и другие способы Pythonic.
Ах, я тоже думал об использовании numpy. Просто немного иначе. См. Мой случай 3.;)
Дело 1: df имеет только единицы и нули в индексах col2 и целых числах.
>>> df
col1 col2
0 a 0
1 b 1
2 c 1
3 d 0
4 c 1
5 d 0
Ты можешь использовать:
>>> df.loc[df['col2'].idxmax() + 1:, 'col2'] = 0
>>> df
col1 col2
0 a 0
1 b 1
2 c 0
3 d 0
4 c 0
5 d 0
Случай2: df может иметь все виды значений в col2 и имеет целочисленные индексы.
>>> df # demo dataframe
col1 col2
0 a 0
1 b 1
2 c 2
3 d 2
4 c 3
5 d 3
Ты можешь использовать:
>>> df.loc[(df['col2'] == 1).idxmax() + 1:, 'col2'] = 0
>>> df
col1 col2
0 a 0
1 b 1
2 c 0
3 d 0
4 c 0
5 d 0
Случай 3: df может иметь все виды значений в col2 и иметь произвольный индекс.
>>> df
col1 col2
u a -1
v b 1
w c 2
x d 2
y c 3
z d 3
Ты можешь использовать:
>>> df['col2'].iloc[(df['col2'].values == 1).argmax() + 1:] = 0
>>> df
col1 col2
u a -1
v b 1
w c 0
x d 0
y c 0
z d 0
Вы можете использовать numpy для эффективного решения:
a = df.col2.values
b = np.zeros_like(a)
b[a.argmax()] = 1
df.assign(col2=b)
col1 col2
0 a 0
1 b 1
2 c 0
3 d 0
4 c 0
5 d 0
Использование drop_duplicates с reindex
df.col2=df.col2.drop_duplicates().reindex(df.index,fill_value=0)
df
Out[1078]:
col1 col2
0 a 0
1 b 1
2 c 0
3 d 0
4 c 0
5 d 0
мне это тоже нравится
data['col2'][np.where(data['col2'] == 1)[0][0]+1:] = 0
Рекомендуется цепная индексация нет.
id = list(df["col2"]).index(1)
df.iloc[id+1:]["col2"].replace(1,0,inplace=True)
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
Рекомендуется цепная индексация нет.
np.flatnonzeroПотому что я думал, что нам нужно больше ответов
df.loc[df.index[np.flatnonzero(df.col2)[1:]], 'col2'] -= 1
df
col1 col2
0 a 0
1 b 1
2 c 0
3 d 0
4 c 0
5 d 0
То же самое, но немного более хитроумно.
df.col2.values[np.flatnonzero(df.col2.values)[1:]] -= 1
df
col1 col2
0 a 0
1 b 1
2 c 0
3 d 0
4 c 0
5 d 0
Вариантов ооочень много, вот мой ... почти такой же, как ответ Timgebs (найден независимо), но все же другой;)
Найдите индекс col2, который имеет первое вхождение 1, и измените все значения строк после этого индекса на 0:
df['col2'].iloc[df.col2.idxmax()+1:] = 0
Будьте осторожны, это устанавливает значения все на 0 после указанного индекса, а не только на те, которые равны 1. Хотя то же самое и с некоторыми другими ответами.
Полностью согласен. Ваше решение более общее.
Можете ли вы придумать хорошее решение для случая, когда индекс произвольный, например,
Index(['u', 'v', 'w', 'x', 'y', 'z'], а col2 может быть чем-то вроде[2, 0, 0, 1, 3, 1]?