Поворот таблицы с повторяющимися записями в Pandas - PullRequest
1 голос
/ 05 марта 2020

Есть ли способ повернуть таблицу Таблицы роста и веса символов пользователя (A) с pandas до (B)? Я пытался использовать unstack, но он не работает.

(A) Таблица роста и веса символов пользователя

+---------------------------------------------+
|     USER_ID    Category    Height    Weight |
+---------------------------------------------+
|     USER 1      Green       172cm      69kg |
|     USER 2      Blue        169cm      61kg |
|     USER 1      Red         153cm      41kg |
|     USER 3      Green       172cm      59kg |
+---------------------------------------------+

(B)

+--------------------------------------------------------------------------------------------------+
| USER_ID Green Height_Green Weight_Green Blue Height_Blue Weight_Blue Red  Height_Red  Weight_Red |
+--------------------------------------------------------------------------------------------------+
| USER 1    1      172.0        69.0        0       0.0       0.0       1      153.0        41.0   |
| USER 2    0        0.0         0.0        1     169.0      61.0       0        0.0         0.0   |            
| USER 3    1      172.0        59.0        0       0.0       0.0       0        0.0         0.0   |
+--------------------------------------------------------------------------------------------------+

Я пытался использовать unstack, но это не похоже на работу. Поскольку существует несколько одинаковых идентификаторов пользователя, pivot_table выдаст мне ValueError, утверждая, что Index содержит повторяющиеся записи и не может изменить форму. Есть ли решение этой проблемы?

df.groupby('USER_ID')['Category','Height', 'Weight'] \
      .apply(lambda x: pd.DataFrame(x.values.tolist(),
             columns=['Category','Height', 'Weight'])) \
      .unstack(fill_value=0)

Ответы [ 4 ]

2 голосов
/ 05 марта 2020

Я бы попытался разбить проблему:

  • сначала преобразовать столбец Высота и Вес в значения с плавающей запятой
  • создаст зеленый, синий и красный столбец, повернув кадр данных с помощью вспомогательный столбец
  • создает столбец type_color с unstack
  • , объединяет вышеприведенный столбец и переиндексирует для получения окончательного кадра данных

Код может быть:

# convert the values to float
for col in ['Height', 'Weight']:
    df[col] = df[col].str.slice(stop=-2).astype('float')

# First columns
tmp1 = df[['USER_ID', 'Category']].assign(val=1).pivot(
    'USER_ID', 'Category', 'val').fillna(0).astype(int)

# Other columns
tmp2 = df.set_index(['USER_ID', 'Category']).unstack().fillna(0)
tmp2.columns = ['_'.join(i) for i in tmp2.columns]

# compute the expected column names
final_cols = [i for j in [[i] + ['_'.join((j,i)) for j in ('Height', 'Weight')]
              for i in ['Green', 'Blue', 'Red']] for i in j]

# finaly produce the result dataframe
resul = pd.concat([tmp1, tmp2], axis=1).reindex(columns=final_cols
                                                ).reset_index()

С вашими исходными данными это дает:

  USER_ID  Green  Height_Green  Weight_Green  Blue  Height_Blue  Weight_Blue  Red  Height_Red  Weight_Red
0  USER 1      1         172.0          69.0     0          0.0          0.0    1       153.0        41.0
1  USER 2      0           0.0           0.0     1        169.0         61.0    0         0.0         0.0
2  USER 3      1         172.0          59.0     0          0.0          0.0    0         0.0         0.0
1 голос
/ 05 марта 2020

Я хотел бы уточнить ваш конечный результат; Я предполагаю, что вы хотите, чтобы они имели значение NaN или какой-либо тип значения, указывающий, что они пустые, а не 0, поскольку это может повлиять на следующий этап обработки.

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

Если я правильно понимаю, вот код для получения что вам нужно

d = {'USER_ID': ['USER 1', 'USER 2', 'USER 1', 'USER 3'],
     "Category": ['Green', 'Blue', 'Red', 'Green'],
     'Height': ['172cm', '169cm', '153cm', '172cm'],
     'Weight': ['69kg', '61kg', '41kg', '59kg']}
df = pd.DataFrame(data=d)
df.pivot(index='USER_ID', columns='Category')

Вы можете посмотреть документацию для сводки здесь:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.pivot.html

0 голосов
/ 05 марта 2020

вы можете использовать melt и pivot_table

import pandas as pd

df = pd.DataFrame([('USER 1', 'Green', '172', '69'),('USER 2', 'Blue', '169', '61'),('USER 1', 'Red', '153', '41'),('USER 3', 'Green', '172', '59')], columns=['USER_ID','Category','Height','Weight'])

df['Color'] =  1 # For the color column

table = pd.melt(df, id_vars=['USER_ID','Category'], value_vars=['Height','Weight', 'Color'])

table['Cat_Var'] = table['Category'] + '_' + table['variable'] 

table = table.pivot_table(values=['value'], index=['USER_ID'],
                    columns=['Cat_Var'], aggfunc='max', fill_value=0)

print(table)

Результат:

             value
Cat_Var Blue_Color Blue_Height Blue_Weight Green_Color Green_Height Green_Weight Red_Color Red_Height Red_Weight
USER_ID
USER 1           0           0           0           1          172           69         1        153         41
USER 2           1         169          61           0            0            0         0          0          0
USER 3           0           0           0           1          172           59         0          0          0
0 голосов
/ 05 марта 2020

Это несколько шагов, так как исходный df не готов к развороту.

  1. для создания кадра данных

       df = pd.DataFrame({
       'UserID': ['USER 1', 'USER 2', 'USER 1', 'USER 3'],
       'Category':  ['Green', 'Blue', 'Red', 'Green'],
       'Height':  [1, 2, 3, 1],
       'Weight': [3.0, 2.0, 2.88, 1.33]
    })
    
  2. Растопить его (отменить сводку), чтобы создать соответствующий формат данных для поворота

    df_m = df.melt(id_vars=['UserID','Category'])

  3. Создать is + color, чтобы на сводной диаграмме мог отображаться цветной столбец

        df_add = df_m[df_m.duplicated(['UserID','Category'])].copy()
        df_add['variable'] = 'IS' + df_add['Category'] 
        df_add['value'] = 1
    
  4. Последний шаг - создание сводной таблицы из df_m .append (df_add)

    pd.pivot_table(df_m.append(df_add),index=['UserID'],columns=['Category','variable'])

...