Применение pd.get_dummies к кадру данных, но изменение вывода

#python #pandas

Вопрос:

Я использую pd.get_dummies в приведенном ниже примере фрейма данных — и он работает правильно, но я хочу посмотреть, есть ли у кого-нибудь идея о том, как изменить результаты. Я опишу ниже:

Оригинальный DF

 ID type AA23 A  AB24 B  DJ44 B KD33 C KD33 A BK89 B BL92 B BL92 C IO89 A  

df после применения: pd.get_dummies(df, столбцы = [‘тип’],префикс = ‘тип’)

 ID type_A type_B type_C AA23 1 0 0  AB24 0 1 0  DJ44 0 1 0 KD33 0 0 1 KD33 1 0 0 BK89 0 1 0 BL92 0 1 0 BL92 0 0 1 IO89 0 0 0  

То, что я ищу, похоже, но для случаев, когда есть 2 или более идентификаторов (например, KD33 или BL92), мне нужна только одна строка на идентификатор и соответствующие столбцы типа, отмеченные 1. Например, с идентификатором = KD33 мне нужна одна строка, где «type_A» и «type_C» имеют 1.

 ID type_A type_B type_C AA23 1 0 0  AB24 0 1 0  DJ44 0 1 0 KD33 1 0 1 BK89 0 1 0 BL92 0 1 1 IO89 0 0 0  

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

1. pd.crosstab(df['ID'], df['type'])

Ответ №1:

Один из вариантов-просто сделать все это с помощью .groupby() :

 In [36]: df.groupby(["ID", "type"]).agg(lambda x: 1).unstack().fillna(0).astype(int).add_prefix("type_") Out[36]: type type_A type_B type_C ID AA23 1 0 0 AB24 0 1 0 BK89 0 1 0 BL92 0 1 1 DJ44 0 1 0 IO89 1 0 0 KD33 1 0 1  

Вы также можете просто прикрепить .groupby его к концу get_dummies версии:

 In [37]: pd.get_dummies(df, columns = ['type'],prefix = 'type').groupby("ID").sum() Out[37]:  type_A type_B type_C ID AA23 1 0 0 AB24 0 1 0 BK89 0 1 0 BL92 0 1 1 DJ44 0 1 0 IO89 1 0 0 KD33 1 0 1  

В этом небольшом примере первая версия немного быстрее, но требует большего количества массирования, чтобы получить тот же формат:

 In [48]: %timeit df.groupby(["ID", "type"]).agg(lambda x: 1).unstack().fillna(0).astype(int).add_prefix("type_") 1.3 ms ± 8.61 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)  In [49]: %timeit pd.get_dummies(df, columns = ['type'],prefix = 'type').groupby("ID").sum() 1.66 ms ± 1.48 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)  

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

1. Спасибо! FWIW второй вариант лучше всего работал с моим фактическим набором данных, который включал другие типы столбцов.

Ответ №2:

Вы можете использовать groupby.size с unstack :

 print (df.groupby(["ID", "type"]).size().unstack(fill_value=0))  type A B C ID  AA23 1 0 0 AB24 0 1 0 BK89 0 1 0 BL92 0 1 1 DJ44 0 1 0 IO89 1 0 0 KD33 1 0 1  

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

1. Не знал об .size() этом и всегда забывал fill_value . 1