Совокупное количество различных строк в столбце на основе значения другого столбца

#pandas

Вопрос:

У меня есть df, который выглядит так с дубликатом удостоверения личности

      ID    Usage_type
0     5    Note
1     6    Note
2     7    Service
3     5    Note
4     7    Note
5     10   Service
 

Мне нужны дополнительные два столбца, которые указывают совокупное количество usage_type для каждого идентификатора, например:

      ID    Usage_type   type_Note    type_Service
0     5    Note         1            0
1     6    Note         1            0
2     7    Service      0            1
3     5    Note         2            0
4     7    Note         1            1
5     10   Service      0            1
 

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

На скриншоте ниже показано, что означает текущий идентификатор для примера введите описание изображения здесь

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

1. Не могли бы вы объяснить, пожалуйста, почему в index 4 у вас есть 1 type_Service ? Я понимаю, почему у type_Note меня там 1, но зачем type_Service ?

2. @sophocles В индексе 2 есть запись Service для идентификатора 7. Идентификатор 7 затем снова появляется в индексе 4 как a Note , поэтому совокупное количество идентификаторов 7 равно 1 для Note , а также 1 для Service

Ответ №1:

Вы можете отфильтровать свой фрейм данных по другому типу Usage_type loc и выполнить групповое кумулятивное подсчет. Наконец, в группе ffill() будут учтены случаи, которые вы объяснили мне в комментариях:

 grp_cc = df.groupby([*df]).cumcount() 1 
df.loc[df.Usage_type=='Note','type_Note'] = grp_cc
df.loc[df.Usage_type=='Service','type_Service'] = grp_cc
 

Это поможет тебе:

    ID Usage_type  type_Note  type_Service
0   5       Note        1.0           NaN
1   6       Note        1.0           NaN
2   7    Service        NaN           1.0
3   5       Note        2.0           NaN
4   7       Note        2.0           NaN
5  10    Service        NaN           1.0
 

А затем, выполнив сгруппированную прямую заливку и заполнив нулевые значения, вы получите то, что вам нужно:

 df = df.groupby('ID').ffill().fillna(0)    

>>> df    
 
   Usage_type  type_Note  type_Service
0       Note        1.0           0.0
1       Note        1.0           0.0
2    Service        0.0           1.0
3       Note        2.0           0.0
4       Note        1.0           1.0
5    Service        0.0           1.0
 

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

1. Я думаю, что решение в вашей правке немного неверно. Индекс 4 должен быть 1,0 для type_Note и 1,0 для type_Service . Есть ли обходной путь для этого? Кроме этого, это именно то, что я ищу!

2. Да, приношу извинения за ошибку, я только что обновил свой ответ, и теперь мы получаем правильный результат.

3. Я попробовал новое решение, но все равно получил неверный подсчет. Опубликовал скриншот выше, показывающий, как это выглядит для 1 идентификатора. В четвертой строке должно быть type_Note = 1 и Type_Service = 3. В пятой строке должно быть type_Note = 1 и Type_Service = 4

Ответ №2:

Я нашел ответ на вашу проблему и решил ее, создав пользовательскую функцию, вот фрагмент кода, который сработал для меня:

 def truefalse(df):
    count=0
    df_2=pd.DataFrame({'col':[0]*(len(df))})
    for i in range(len(df)):
        if df[i] == True:
            df_2['col'][i]=count 1
            count =1
    return df_2
ID=[5,6,7,5,7,10]
usg=['Note','Note','Service','Note','Note','Service']
df=pd.DataFrame({'ID':ID,'Usage_type':usg})
for unid in df['ID'].unique():
     df['type_Note'] = truefalse(((df['Usage_type'] =='Note') amp; ( df['ID'] ==unid)))['col'] df['type_Note']
     df['type_Service'] = truefalse(((df['Usage_type'] =='Service) amp; ( df['ID'] ==unid)))['col'] df['type_Note'] 
 

Надеюсь, это поможет!

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

1. Есть ли способ реализовать это в исходном фрейме данных (т. Е. Просто добавить два дополнительных столбца в конце)?

2. Ну, код, который я показал, добавляет 1 столбец в исходный кадр данных, если вы хотите сделать это для обоих, просто сделайте это так:. для идентификатора unid в df[‘ID’].уникальный(): df[‘type_Note’] = truefalse(((df[‘Usage_type’] ==’Примечание’) amp; ( df[‘ID’] ==unid)))[‘col’] df[‘type_Note’]. df[‘type_Service’] = truefalse(((df[‘Usage_type’] ==’Услуга) amp; ( df[‘ID’] ==unid)))[‘col’] df[‘type_Note’]