Как заполнить произвольные пропущенные даты в кадре данных Pandas? - PullRequest
0 голосов
/ 30 мая 2018

Мой текущий фрейм данных:

   |   user  |       date        | count|
   | ------  | ------------------| -----|
   | user 1  | 2017-11-09        |   3  |
   | user 1  | 2017-11-12        |   4  |
   | user 1  | 2017-11-14        |   5  |
   | user 2  | 2017-11-11        |   2  |
   | user 2  | 2017-11-12        |   6  |
   | user 2  | 2017-11-14        |   7  |

Что бы я хотел, чтобы это было:

   |   user  |       date        | count|
   | ------  | ------------------| -----|
   | user 1  | 2017-11-09        |   3  |
   | user 1  | 2017-11-10        |   0  |
   | user 1  | 2017-11-11        |   0  |
   | user 1  | 2017-11-12        |   4  |
   | user 1  | 2017-11-13        |   0  | 
   | user 1  | 2017-11-14        |   5  |
   | user 2  | 2017-11-09        |   0  |
   | user 2  | 2017-11-10        |   0  |
   | user 2  | 2017-11-11        |   2  |
   | user 2  | 2017-11-12        |   6  |
   | user 2  | 2017-11-13        |   0  | 
   | user 2  | 2017-11-14        |   7  |

Есть предложения?Я пытался сделать метод resample, но я не уверен, что он работает.Кроме того, мои даты уже преобразованы в объекты datetime.

РЕДАКТИРОВАТЬ: Я благодарен за ответы, но я понял, что мой столбец даты имеет несколько одинаковых дат, и индексация теперь является проблемойпотому что есть повторяющиеся даты.Есть ли способ решить проблему, которая не требует индексации (или обходит ее?)

Ответы [ 3 ]

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

Вы можете создать date_range и использовать merge

Пример:

>>> pd.date_range(start=df.date.min(), end=df.date.max(), freq='1D')

DatetimeIndex(['2017-11-09', '2017-11-10', '2017-11-11', '2017-11-12',
               '2017-11-13', '2017-11-14'],
              dtype='datetime64[ns]', freq='D')

Тогда

df2 = pd.DataFrame((pd.date_range(start=df.date.min(), end=df.date.max(), freq='1D')), columns=["date"])
pd.merge(df2,df, on="date", how="left").fillna(0)

date    count
0   2017-11-09  3.0
1   2017-11-10  0.0
2   2017-11-11  0.0
3   2017-11-12  4.0
4   2017-11-13  0.0
5   2017-11-14  5.0
0 голосов
/ 30 мая 2018

@ Ответ Джезраэль действительно потрясающий!Просто добавим немного, если вы хотите использовать произвольный диапазон дат:

more_dates = pd.date_range('20171101', '20171120')
df = df.reindex(more_dates, fill_value=0)

            count
2017-11-01    0.0
2017-11-02    0.0
2017-11-03    0.0
2017-11-04    0.0
2017-11-05    0.0
2017-11-06    0.0
2017-11-07    0.0
2017-11-08    0.0
2017-11-09    3.0
2017-11-10    0.0
2017-11-11    0.0
2017-11-12    4.0
2017-11-13    0.0
2017-11-14    5.0
2017-11-15    0.0
2017-11-16    0.0
2017-11-17    0.0
2017-11-18    0.0
2017-11-19    0.0
2017-11-20    0.0

Спасибо @jezrael за совет, отредактированный.

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

Использовать asfreq, работая с DatetimeIndex, поэтому сначала set_index:

#if necessary convert to datetimes
#df['date'] = pd.to_datetime(df['date'])

df = df.set_index('date').asfreq('d', fill_value=0)
print (df)
            count
date             
2017-11-09      3
2017-11-10      0
2017-11-11      0
2017-11-12      4
2017-11-13      0
2017-11-14      5

Если есть дубликаты DatetimeIndex, необходимоresample с некоторой статистической функцией, такой как sum:

df = df.set_index('date').resample('d').sum()

РЕДАКТИРОВАТЬ, если вам не нужны все комбинации дат:

df = (df.set_index('date').groupby('user')['count']
        .apply(lambda x: x.asfreq('d', fill_value=0))
        .reset_index())
print (df)
     user       date  count
0  user 1 2017-11-09      3
1  user 1 2017-11-10      0
2  user 1 2017-11-11      0
3  user 1 2017-11-12      4
4  user 1 2017-11-13      0
5  user 1 2017-11-14      5
6  user 2 2017-11-11      2
7  user 2 2017-11-12      6
8  user 2 2017-11-13      0
9  user 2 2017-11-14      7

РЕДАКТИРОВАТЬ1 Для всех комбинаций дат:

mux = pd.MultiIndex.from_product([df['user'].unique(), pd.date_range(df['date'].min(), df['date'].max())],
                                 names=['user','date'])
df = df.set_index(['user', 'date']).reindex(mux, fill_value=0).reset_index()
print (df)
      user       date  count
0   user 1 2017-11-09      3
1   user 1 2017-11-10      0
2   user 1 2017-11-11      0
3   user 1 2017-11-12      4
4   user 1 2017-11-13      0
5   user 1 2017-11-14      5
6   user 2 2017-11-09      0
7   user 2 2017-11-10      0
8   user 2 2017-11-11      2
9   user 2 2017-11-12      6
10  user 2 2017-11-13      0
11  user 2 2017-11-14      7
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...