#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 у вас есть 1type_Service
? Я понимаю, почему уtype_Note
меня там 1, но зачемtype_Service
?2. @sophocles В индексе 2 есть запись
Service
для идентификатора 7. Идентификатор 7 затем снова появляется в индексе 4 как aNote
, поэтому совокупное количество идентификаторов 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’]