Панды, заполняющие недостающие даты и значения в группе дублирующимися индексными значениями - PullRequest
0 голосов
/ 14 мая 2018

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

import pandas as pandas

x = pandas.DataFrame({'user': ['a','a','b','b','a'], 'dt': ['2016-01-01','2016-01-02', '2016-01-05','2016-01-06','2016-01-06'], 'val': [1,33,2,1,2]})
udates=x['dt'].unique()
x['dt'] = pandas.to_datetime(x['dt'])
dates = x.set_index(udates).resample('D').asfreq().index
users=x['user'].unique()
idx = pandas.MultiIndex.from_product((dates, users), names=['dt', 'user'])
x.set_index(['dt', 'user']).reindex(idx, fill_value=0).reset_index()
print(x)

Желаемый вывод

          dt user  val
0  2016-01-01    a    1
2  2016-01-02    a   33
4  2016-01-03    a    0
6  2016-01-04    a    0
8  2016-01-05    a    0
10 2016-01-06    a    2
1  2016-01-01    b    0
3  2016-01-02    b    0
5  2016-01-03    b    0
7  2016-01-04    b    0
9  2016-01-05    b    2
11 2016-01-06    b    1

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Другой способ менее элегантный, чем @sacul ..., но почти такой же скорости.

import pandas as pd
x = pd.DataFrame({'user': ['a','a','b','b','a'],
                  'dt': ['2016-01-01','2016-01-02',
                         '2016-01-05','2016-01-06','2016-01-06'],
                  'val': [1,33,2,1,2]})

users = pd.unique(x.user)
x.dt = pd.to_datetime(x.dt)
dates = pd.date_range(min(x.dt), max(x.dt))
x.set_index('dt', inplace=True)

df = pd.DataFrame(index=dates)
for u in users:
    df[u] = x[x.user==u].val

df = df.unstack().reset_index()
df.rename(columns={'level_0': 'user',
                    'level_1': 'dt',
                    0: 'val'}, inplace=True)
df.val.fillna(0, inplace=True)
df.val = df.val.astype(int)
df = df[['dt', 'user', 'val']]

df:

            dt user  val
0   2016-01-01    a    1
1   2016-01-02    a   33
2   2016-01-03    a    0
3   2016-01-04    a    0
4   2016-01-05    a    0
5   2016-01-06    a    2
6   2016-01-01    b    0
7   2016-01-02    b    0
8   2016-01-03    b    0
9   2016-01-04    b    0
10  2016-01-05    b    2
11  2016-01-06    b    1
0 голосов
/ 14 мая 2018

Вот один из способов, переиндексировать каждый user, чтобы иметь диапазон дат от минимальной даты до вашей максимальной даты:

# setup your dataframe as you had it before:
x = pandas.DataFrame({'user': ['a','a','b','b','a'], 'dt': ['2016-01-01','2016-01-02', '2016-01-05','2016-01-06','2016-01-06'], 'val': [1,33,2,1,2]})
udates=x['dt'].unique()
x['dt'] = pandas.to_datetime(x['dt'])

# fill with new dates:
filled_df = (x.set_index('dt')
             .groupby('user')
             .apply(lambda d: d.reindex(pd.date_range(min(x.dt),
                                                      max(x.dt),
                                                      freq='D')))
             .drop('user', axis=1)
             .reset_index('user')
             .fillna(0))


>>> filled_df
           user   val
2016-01-01    a   1.0
2016-01-02    a  33.0
2016-01-03    a   0.0
2016-01-04    a   0.0
2016-01-05    a   0.0
2016-01-06    a   2.0
2016-01-01    b   0.0
2016-01-02    b   0.0
2016-01-03    b   0.0
2016-01-04    b   0.0
2016-01-05    b   2.0
2016-01-06    b   1.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...