измените фрейм данных на другую структуру в соответствии с идентификатором

#python #pandas #numpy

Вопрос:

Мой начальный фрейм данных pandas выглядит следующим образом:

 df = pd.DataFrame(np.array([[999,888,1,0], [988,899,2,0], [981,821,3,0],[721,789,4,1],[723,745,5,1],[444,432,6,2],[423,412,7,2],[423,455,8,2],[478,432,9,2]]),  columns=['a', 'b', 'c', 'id'])  gt;gt;gt;df a b c id 999 888 1 0 988 899 2 0 981 821 3 0 721 789 4 1 723 745 5 1 444 432 6 2 423 412 7 2 423 455 8 2 478 432 9 2   

Теперь я хочу создать новый фрейм данных со следующей структурой:

 0 1 2 3 4 5 999 988 888 899 1 2 721 723 789 745 4 5 444 423 432 412 6 7  

Так что на самом деле я просто хочу получить первые два значения каждого идентификатора и каждого столбца (a,b,c). Пример: первая строка -gt; col a: 999, 988 col b: 888, 899 col c: 1, 2

Редактировать: Благодаря Коррелиану я использую следующий код:

 size = 3   data = df.groupby('id').head(2).melt('id').sort_values(by=['id', 'variable'])['value'] out = pd.DataFrame(data.values.reshape((size, -1)))  

Ответ №1:

Вычислите количество значений id , чтобы получить размер (количество уникальных идентификаторов, здесь 3) и наименьшее количество (здесь 2 для идентификатора=1). Сгруппируйте id и сохраните первую count строку для каждой используемой группы head .

Затем используйте melt для выравнивания фрейма данных и сортировки его по id . Наконец, измените свой фрейм данных в соответствии с size переменной и создайте новый фрейм данных:

 size, count = df.value_counts('id').agg(['size', 'min']) data = df.groupby('id').head(count).melt('id').sort_values('id')['value'] out = pd.DataFrame(data.values.reshape((size, -1))) print(out)  # Output:  0 1 2 3 0 999 988 888 899 1 721 723 789 745 2 444 423 432 412  

Обновить

Я изменил свой начальный фрейм данных на 3 столбца (a,b,c) см. Мой первоначальный вопрос. Как я должен изменить ваш код?

 size, count = df.value_counts('id').agg(['size', 'min']) m = df.groupby('id').head(count).iloc[:, :-1].values df = pd.DataFrame(np.hstack(m.T.reshape(-1, size, count))) print(df)  # Output:  0 1 2 3 4 5 0 999 988 888 899 1 2 1 721 723 789 745 4 5 2 444 423 432 412 6 7  

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

1. Я изменил свой начальный фрейм данных на 3 столбца (a,b,c) см. Мой первоначальный вопрос. Как я должен изменить ваш код? Я пытался, но не преуспел..

Ответ №2:

Этого можно было бы достичь следующим образом:

 pd.DataFrame(df.groupby("id").head(2).set_index('id').values.flatten().reshape((3,4)))  

Редактировать

Новым примером может быть:

 pd.DataFrame(df.groupby("id").head(2).set_index('id').values.flatten().reshape((3,6)))[[0,1,3,4,2,5]]  

С помощью этого метода вы должны изменить порядок столбцов, чтобы получить желаемый результат.

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

1. Ваш ответ абсолютно верен (для двух столбцов). Однако я изменил свой исходный фрейм данных на 3 столбца (a,b,c). См. Мой первоначальный вопрос. Как я должен изменить ваш код? Я пытался, но безуспешно..