#pandas #dataframe
#панды #фрейм данных
Вопрос:
У меня есть фрейм данных, имеющий два типа строк: ПЕРЕКЛЮЧАТЕЛЬ и РЕЗУЛЬТАТ.Я ожидаю, что отброшу соседний «ПЕРЕКЛЮЧАТЕЛЬ» и сохраню только последний ПЕРЕКЛЮЧАТЕЛЬ в блоке, но сохраню все строки РЕЗУЛЬТАТОВ.
Я сделал это с помощью итераций фреймов данных и в основном сканировал строку за строкой. Это не по-питонски. Не могли бы вы, пожалуйста, посоветовать, видите ли вы лучший способ? Ниже приведены примеры данных и код, который я использую:
import pandas as pd data = {'TYPE':['SWITCH','SWITCH','SWITCH', 'SWITCH','RESULT','RESULT','RESULT', 'RESULT','RESULT','SWITCH','SWITCH', 'RESULT','RESULT','RESULT','RESULT'], 'RESULT':['YES', 'NO','NO','YES', 'DONE','DONE','DONE', 'DONE','DONE','NO', 'YES','DONE','DONE', 'DONE','DONE']} df = pd.DataFrame(data) l = [] start=-1 for index, row in df.iterrows(): type = row["TYPE"] if type == "RESULT": if start == -1: start = index elif type == "SWITCH": if start== -1: df.drop(index=[*range(index, index 1, 1)], inplace=True) continue end = index-1 if start lt;= end: df.drop(index=[*range(start,end,1)], inplace=True) start = index 1 print(df)
Просто проверил вывод и обнаружил, что мой код не сделал того, что я ищу:
Перед применением кода
Поскольку индекс 0~индекс 3 все являются «ПЕРЕКЛЮЧАТЕЛЯМИ», я хочу удалить индекс 0/1/2 и сохранить только индекс 3, так как это «блок переключения» Аналогично, для индекса 9/10 я хочу сохранить только индекс 10
TYPE RESULT 0 SWITCH YES 1 SWITCH NO 2 SWITCH NO 3 SWITCH YES 4 RESULT DONE 5 RESULT DONE 6 RESULT DONE 7 RESULT DONE 8 RESULT DONE 9 SWITCH NO 10 SWITCH YES 11 RESULT DONE 12 RESULT DONE 13 RESULT DONE 14 RESULT DONE
Ожидаемый результат:
TYPE RESULT 3 SWITCH YES 4 RESULT DONE 5 RESULT DONE 6 RESULT DONE 7 RESULT DONE 8 RESULT DONE 10 SWITCH YES 11 RESULT DONE 12 RESULT DONE 13 RESULT DONE 14 RESULT DONE
Фактический объем производства:
TYPE RESULT 8 RESULT DONE 9 SWITCH NO 10 SWITCH YES 11 RESULT DONE 12 RESULT DONE 13 RESULT DONE 14 RESULT DONE
Комментарии:
1. Не могли бы вы уточнить, что вы подразумеваете под «только в блоке»? Также не могли бы вы добавить предполагаемый результат.
2. Спасибо @j__Карлсон. Я просто добавил немного больше описания. Надеюсь, теперь все стало яснее
Ответ №1:
Если я вас правильно понимаю, для каждой группы последовательных строк с TYPE == "SWITCH"
вами нужно сохранить последнюю строку. Это можно сделать следующим образом:
df_processed = df[(df.TYPE != "SWITCH") | (df.TYPE.shift(-1) != "SWITCH")]
Выходные данные для приведенного примера данных являются
Комментарии:
1. Это такое умное однострочное решение!
Ответ №2:
Повторение строк фрейма данных считается плохой практикой, и его следует избегать.
Я верю, что вы ищете что-то в этом роде:
# Get the rows where TYPE == RESULT df_type_result = df[df['TYPE'] == 'RESULT'] # Get the last index when the result type == SWITCH idxs = df.reset_index().groupby(['TYPE', 'RESULT']).last().loc['SWITCH']['index'] df_type_switch = df.loc[idxs] # Concatenate and sort the results df_result = pd.concat([df_type_result, df_type_switch]).sort_index() df_result
Комментарии:
1. Извините, что я создал путаницу в моем первоначальном описании вопроса — да, повторение строки-это худшее 🙂 Я принял решение @Anton, которое довольно изящно, но все равно спасибо вам
Ответ №3:
Ленивое решение
df["DROP"] = df["TYPE"].shift(-1) df = df.loc[~((df["TYPE"]=="SWITCH")amp;(df["DROP"]=="SWITCH"))] df.drop(columns="DROP", inplace=True)
Комментарии:
1. Извините, я должен был выразиться яснее. Я думаю, что ваше решение имеет аналогичную стратегию @Anton, и оно также может генерировать желаемый результат. Огромное спасибо
2. Да, именно более длинная версия :))