панды вычисляют общее количество предыдущих последовательных строк

#python #python-3.x #pandas #dataframe

Вопрос:

У меня есть фрейм данных:

 data = {'process': ['buying','selling','searhicng','repairing', 'preparing', 'selling','buying', 'searching', 'selling','searching'],
        'type': ['in_progress','in_progress','end','in_progress', 'in_progress', 'end','in_progress', 'end', 'in_progress','end'],
'country': ['usa','usa', 'usa','ghana', 'ghana','ghana','ghana', 'ghana', 'albania','albania'],
'id': ['022','022','022', '011','011', '011','011', '011', '6','6'],
'duration': [1,1,4,1,2,1,2,3,4,1]       
}
df = pd.DataFrame(data, columns = ['process','type','country', 'id', 'duration'])
 

введите описание изображения здесь

Мне нужно рассчитать общую продолжительность для строк, где type=in_progress и до значения type=end , и создать новый столбец process_line , содержащий список значений из process столбца

Кто-нибудь может мне помочь

Выходной кадр данных:

введите описание изображения здесь

Я попытался пронумеровать каждую строку, а затем выбрать строки с type=in_progress вычислением общей продолжительности и списком ящиков процесса, но это работает очень медленно

 from tqdm import  tqdm
k = 0
temp=pd.DataFrame()
res = pd.DataFrame()
for i in tqdm(list(df.drop_duplicates('id').id)):
    k=0
    temp = df[df.id==i]
    for index, row in temp.iterrows():
        if row.type=='end':
            number = pd.DataFrame([row])
            number['nn'] = k
            res = pd.concat([res,number])
            k =1
        else:
            number = pd.DataFrame([row])
            number['nn'] = k
            res = pd.concat([res,number])
 

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

1. Что ты уже пробовал. Каковы ваши идеи?

2. Спасибо за вопрос, я только что добавил его в запрос

Ответ №1:

Что-то вроде этого?

 df['type_groups'] = df['type'].shift(1).eq('end').cumsum()
df2 = df[df['type'] != 'end'].groupby('type_groups').agg({'process': list, 
                                                          'country': 'first', 
                                                          'id': 'first', 
                                                          'duration': sum})

 
Результат
группы типов процесс Страна ID Продолжительность
0 [«покупка», «продажа»] США 022 2
1 [«ремонт», «подготовка»] гана 011 3
2 [«покупка»] гана 011 2
3 [«продажа»] албания 6 4

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

1. Похоже, что столбцы с «searhicng» не следует учитывать при расчете продолжительности.

2. Это похоже на мой результат, но мы не рассматривали строки с типом=конец при вычислении и создании списка процессов

3. Каково желаемое поведение. Должны ли считаться только строки, которые закончились? Если отсутствует конец, к какому результату вы стремитесь? Не могли бы вы разместить нужную таблицу с парой крайних случаев?

4. Если вам нужно исключить «конечные» строки, мы можем отфильтровать их перед группировкой (см. Мой обновленный ответ). Но, похоже, ты понял это сам!

Ответ №2:

с помощью @fsimonjetz я понял, как я могу это сделать

  df['nn'] = df['type'].shift(1).eq('end').cumsum()
in_progress_df = df[df.type=='in_progress'].reset_index()
end_df = df[df.type=='end'].reset_index()



in_progress_grouped = in_progress_df.groupby('nn').agg({'process':list,
                               'type':'last',
                               'country':'first',
                               'id':'first',
                               'duration':sum,
                               'nn':'first'})
                        .rename(columns={'nn':'number'})

res = pd.merge(in_progress_df,end_df , left_on='nn', right_on='nn').drop(labels=['type_x','country_x','id_x','duration_y','index','nn'],axis=1)