Как изменить форму панды с длинным на широкий, после заполнения пропущенного значения по категории? - PullRequest
0 голосов
/ 23 мая 2019

У меня есть следующий пример набора данных

df  = pd.DataFrame({'Id': {0:'user_id1', 1:'user_id1', 2:'user_id1', 3:'user_id1',
                          4:'user_id2', 5:'user_id2',  6:'user_id2'},

                   'hr' :{0:1, 1:2, 2:3, 3:4, 4:1, 5:2, 6:3},
                   'value': {0:17, 1:20, 2:12, 3:10, 4:11, 5:20, 6:13},
                   'result': {0:12, 1:21, 2:32, 3:16, 4:41, 5:50, 6:53}})
df

enter image description here

Первое: каждый пользователь должен иметь значение в столбце result и value в каждый час ( hr ). Но если нет значения или результата , тогда я должен создать пропущенный час ( ч ) и добавить новую строку со значением медианы для каждого столбца. Час всегда находится в диапазоне от 1 до 4.

Пример: - user_id2 не имеет записи в ч = 4 . Итак, я возьму медиану других часов из результат столбец, т. Е.

np.median ([[41, 50, 53]) => 50.

Аналогично для значение столбец:

np.median ([11, 20, 13]) = 13

Это приведет к добавлению новой строки для user_id2 в ч = 4 , как показано ниже: enter image description here

Наконец: я хочу преобразовать вышеуказанный длинный формат в более широкий, чтобы каждый user_id {i} имел все значения, представленные в одном векторе [raw] для ч как показано ниже: enter image description here

Я ценю любую помощь.

Ответы [ 2 ]

3 голосов
/ 23 мая 2019

Попробуйте:

1) Используйте pandas.MultiIndex.from_product и reindex для создания отсутствующих строк.Затем используйте DataFrame.groupby.median, чтобы создать fillna значения

midx = pd.MultiIndex.from_product([df['Id'].unique(), [1, 2, 3, 4]], names=['Id', 'hr'])
medians = df.groupby('Id').median()
df_new = df.set_index(['Id', 'hr']).reindex(midx).fillna(medians).reset_index()

2) Измените DataFrame, используя комбинацию set_index, stack и unstack

df_new = df_new.set_index(['Id', 'hr']).stack().unstack([1, 2])
df_new.sort_index(axis=1, level=[0, 1])

3) Исправить имена столбцов с помощью списка

df_new.columns = ['hr_{}_{}'.format(x[0], x[1]) for x in df_new.columns]

[out]

         hr_1_value  hr_1_result  hr_2_value  hr_2_result  hr_3_value  hr_3_result  hr_4_value  hr_4_result
Id                                                                                                                 
user_id1        17.0         12.0        20.0         21.0        12.0        32.0        10.0         16.0
user_id2        11.0         41.0        20.0         50.0        13.0        53.0        13.0         50.0
1 голос
/ 23 мая 2019

Попробуйте:

new_index = pd.MultiIndex.from_product([df.Id.unique(), df.hr.unique()],
                                       names=['Id', 'hr'])

df = df.set_index(['Id', 'hr']).reindex(new_index)

# fillna
new_df = (df.groupby('Id')
            .apply(lambda x: x.fillna(x.median()))
            .unstack(level=1)
         )

new_df.columns = [f'hr_{b}_{a}' for a,b in new_df.columns]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...