Панды преобразуют длину в ширину на основе нескольких меток(составных ключей)

#python #pandas #pivot #pandas-groupby #reshape

Вопрос:

У меня есть фрейм данных, который выглядит примерно так

 df_input = pd.DataFrame({'datatype':['IN','IN','EX','EX','IN','IN','EX','EX'], 'Time': [0,0,0,0,1,1,1,1], 'filetype': ['img','txt','img','txt','img','txt','img','txt']}, index=['PMSN01001','PMSN01001','PMSN01001','PMSN01001','PMSN01001','PMSN01001','PMSN01001','PMSN01001'])

print(df_input)

id          datatype    Time    filetype
PMSN01001   IN        0       img
PMSN01001   IN        0       txt
PMSN01001   EX        0       img
PMSN01001   EX        0       txt
PMSN01001   IN        1       img
PMSN01001   IN        1       txt
PMSN01001   EX        1       img
PMSN01001   EX        1       txt
 

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

ничего не стоящий, для каждого идентификатора, с комбинацией [‘тип данных’, ‘Время’, ‘тип файла’], может составлять до 8 записей данных(2x2x2). Поэтому поворотные столбцы также должны соответствующим образом отражать … я думаю..

 df_output = pd.DataFrame({'datatype_time0':['IN'], 'Time_time0': [0], 'filetype_time0': ['img'],'filetype2_time0':['txt'], 'datatype_time1':['EX'], 'Time_time1':[1],  'filetype_time1': ['img'],'filetype2_time1':['txt']}, index=['PMSN01001'])
df_output
           datatype_time0   Time_time0  filetype_time0  filetype2_time0      datatype_time1 Time_time1  filetype_time1  filetype2_time1
 PMSN01001    IN                 0              img          txt               EX              1                 img              txt    
                                                             
 

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

Спасибо

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

1. @jezrael, мне жаль, что я совершил огромную ошибку. проще говоря, один идентификатор может содержать до 8 записей, основанных на комбинации [«тип данных», «Время», «тип файла»]. Поэтому задача состоит в том, чтобы сделать их в широком формате. Я обновил контент, лучше всего

2. Хм, так нужно ли сначала удалять дубликаты?

3. если я правильно вас понял. сам идентификатор дублируется, но разве все они не составляют минимальную уникальную запись данных на основе комбинации [тип данных, время, тип файла] ?

4. Так нужно, как будто x = df.groupby(['id', 'datatype']).agg(Time=('Time', 'first'), filetype1=('filetype', 'first'), filetype2=('filetype', 'last')) это означает «первый и последний filetype ['id', 'datatype'] «? Ты уверен?

5. я чувствую, что df.groupby ([«идентификатор», «тип данных», «Время», «тип файла»]) имеет больше смысла, потому что я использую id 3 ключа в качестве составного ключа priamry

Ответ №1:

Попробуйте использовать groupby , cumcount и pivot_table :

 x = df.groupby(['id', 'datatype']).agg(Time=('Time', 'first'), filetype1=('filetype', 'first'), filetype2=('filetype', 'last'))
x = x.assign(idx=x.groupby(level=0).cumcount()   1).reset_index().pivot_table(index=['id'], columns='idx', 
                    values=['datatype', 'Time', 'filetype1', 'filetype2'], aggfunc='first')
x = x.sort_index(axis=1, level=1)
x = x.set_axis([f'{x}_{y}' for x,y in x.columns], axis=1).reset_index()
 

 >>> x
          id  Time_1 datatype_1 filetype1_1 filetype2_1  Time_2 datatype_2 filetype1_2 filetype2_2
0  PMSN01001       1         EX         img         txt       0         IN         img         txt
>>> 
 

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

1. спасибо, ваше решение было полезным, но могу ли я спросить, почему это df.groupby ([«идентификатор», «тип данных»]) вместо df.groupby ([«идентификатор», «тип данных», «Время», «тип файла»])?

2. @WonChulChung Это потому, что именно эти столбцы делают разделение 🙂 и вы могли бы указать больше столбцов, но просто этих двух достаточно, чтобы определить разделение. Не стесняйтесь отмечать и озвучивать это, если вы считаете, что это полезно 🙂