Панды присваивают значение на основе следующей строки(строк)

#python #pandas

Вопрос:

Рассмотрим этот простой фрейм данных pandas со столбцами «запись», «начало» и «параметры». Может быть несколько строк с одним и тем же значением записи, и каждое уникальное значение записи соответствует одному и тому же начальному значению. Однако значение «параметр» может отличаться для одной и той же комбинации «запись» и «начало»:

 pd.DataFrame({'record':[1,2,3,4,4,5,6,7,7,7,8], 'start':[0,5,7,13,13,19,27,38,38,38,54], 'param':['t','t','t','u','v','t','t','t','u','v','t']})  

Я хотел бы создать столбец «конец», который принимает значение «начало» в строке со следующим уникальным значением «запись». Значения столбца «конец» должны быть:

 [5,7,13,19,19,27,38,54,54,54,NaN]  

Я могу сделать это с помощью цикла for, но я знаю, что это не предпочтительно при использовании панд:

 max_end = 100 for idx, row in df.iterrows():  try:  n = 1  next_row = df.iloc[idx n]  while next_row['start'] == row['start']:  n = n 1  next_row = df.iloc[idx n]  end = next_row['start']  except:  end = max_end  df.at[idx, 'end'] = end  

Есть ли простой способ добиться этого без цикла for?

Комментарии:

1. Я верю, что ты что-то пробовал, верно? Пожалуйста, предоставьте свою попытку здесь, и не могли бы вы немного объяснить, как был создан этот конечный столбец(Условия….)?

Ответ №1:

Я не сомневаюсь, что есть более разумное решение, но вот мое.

 df1['end'] = df1.drop_duplicates(subset = ['record', 'start'])['start'].shift(-1).reindex(index = df1.index, method = 'ffill')  

-=РЕДАКТИРОВАТЬ=- Добавлено подмножество drop_duplicates для учета поправки к вопросу

Комментарии:

1. Это сработало для примера, который я опубликовал. Я понял, что должен был предоставить более подробный пример того, что я делаю, потому что это не работает при использовании моего реального фрейма данных. Я обновил вопрос, чтобы отразить это!

2. Попробуйте сейчас, должно быть только удаление дубликатов среди этих столбцов

Ответ №2:

Это решение эквивалентно @Quixotic22, хотя и более явное.

 df = pd.DataFrame({ 'record':[1,2,3,4,4,5,6,7,7,7,8], 'start':[0,5,7,13,13,19,27,38,38,38,54], 'param':['t','t','t','u','v','t','t','t','u','v','t'] }) max_end = 100  df["end"] = None # create new column with empty values loc = df["record"].shift(1) != df["record"] # record where the next value is diff from previous  df.loc[loc, "end"] = df.loc[loc, "start"].shift(-1) # assign desired values df["end"].fillna(method = "ffill", inplace = True) # fill remaining missing values df.loc[df.index[-1], "end"] = max_end # override last value  df