Создайте новые фреймы данных для каждого уникального значения в столбце в pandas

#python #pandas #dataframe

Вопрос:

У меня есть фрейм данных присутствия/отсутствия, который выглядит следующим образом (он намного больше, но уменьшил его для этого вопроса).:

 annotations factor1 factor2 factor3 Class heroine 1 0 1 OPIOID_TYPE he smokes 0 1 0 OTHER_DRUG_USE heroin 1 0 1 OPIOID_TYPE  

Что я хотел бы сделать, так это создать новый фрейм данных для каждого уникального значения в «Классе» и вставить каждое значение в класс в качестве имени последнего столбца для каждого фрейма данных и записать наличие/отсутствие.

Другими словами:

 annotations factor1 factor2 factor3 OPIOID_TYPE heroine 1 0 1 1 he smokes 0 1 0 0 heroin 1 0 1 1  

и:

 annotations factor1 factor2 factor3 OTHER_DRUG_USE heroine 1 0 1 0 he smokes 0 1 0 1 heroin 1 0 1 0  

На самом деле мой фрейм данных намного больше: 2289 строк и 1273 столбца и ровно 23 уникальных значения в «Классе» для 23 новых фреймов данных.

Я предполагаю, что здесь будет работать структура цикла, но у меня ограниченный опыт работы с циклами python.

Ответ №1:

Вы можете перебирать свои Class значения:

 dfs = {} for klass in df['Class'].unique():  dfs[klass] = df.assign(**{klass: df['Class'].eq(klass).astype(int)})   .drop(columns='Class')  

Теперь у вас есть диктант, индексированный по Class значениям:

 gt;gt;gt; dfs.keys() dict_keys(['OPIOID_TYPE', 'OTHER_DRUG_USE'])  gt;gt;gt; dfs['OPIOID_TYPE']  annotations factor1 factor2 factor3 OPIOID_TYPE 0 heroine 1 0 1 1 1 he smokes 0 1 0 0 2 heroin 1 0 1 1  gt;gt;gt; dfs['OTHER_DRUG_USE']  annotations factor1 factor2 factor3 OTHER_DRUG_USE 0 heroine 1 0 1 0 1 he smokes 0 1 0 1 2 heroin 1 0 1 0  

Настоятельно не рекомендуется следующее

Теперь, если вам действительно нужны реальные переменные python, вы можете использовать locals() их для динамического создания:

 for idx, klass in enumerate(df['Class'].unique(), 1):  print(f"df{idx} is for '{klass}' class")  locals()[f"df{idx}"] = df.assign(**{klass: df['Class'].eq(klass).astype(int)})   .drop(columns='Class')  # Output: df1 is for 'OPIOID_TYPE' class df2 is for 'OTHER_DRUG_USE' class  

Выход:

 gt;gt;gt; df1  annotations factor1 factor2 factor3 OPIOID_TYPE 0 heroine 1 0 1 1 1 he smokes 0 1 0 0 2 heroin 1 0 1 1  gt;gt;gt; df2  annotations factor1 factor2 factor3 OTHER_DRUG_USE 0 heroine 1 0 1 0 1 he smokes 0 1 0 1 2 heroin 1 0 1 0  

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

1. Спасибо! Я не совсем уверен, что происходит во второй части, но есть ли способ извлечь каждый «кадр данных» в дикте для ряда объектов? т. е. df1 — df23?

2. Вторая часть-это то, что вы хотите, динамически создавать переменные. Я обновил свой ответ на основе вашего комментария. Теперь вы можете использовать df1, df2, …, df23 в качестве независимых кадров данных.

Ответ №2:

Мы можем сделать get_dummies и сохранить dfs в dict

 s = df.pop('Class').str.get_dummies() d = {x : df.join(s[[x]]) for x in s}  

Пример вывода ниже

 d['OPIOID_TYPE'] Out[43]:   annotations factor1 factor2 factor3 OPIOID_TYPE 0 heroine 1 0 1 1 1 hesmokes 0 1 0 0 2 heroin 1 0 1 1 d['OTHER_DRUG_USE'] Out[44]:   annotations factor1 factor2 factor3 OTHER_DRUG_USE 0 heroine 1 0 1 0 1 hesmokes 0 1 0 1 2 heroin 1 0 1 0  

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

1. Большое вам спасибо! Есть ли способ извлечь каждый из них в виде отдельных кадров данных из диктанта?