Панды: заполнение данных для пропущенных дат - PullRequest
4 голосов
/ 09 апреля 2019

Допустим, у меня есть следующая таблица:

ProdID  Date        Val1 Val2 Val3
Prod1   4/1/2019    1    3    4
Prod1   4/3/2019    2    3    54
Prod1   4/4/2019    3    4    54
Prod2   4/1/2019    1    3    3
Prod2   4/2/2019    1    3    4
Prod2   4/3/2019    2    4    4
Prod2   4/4/2019    2    5    3

Prod2 записи заполнены правильно, так как мы получили данные от 4/1/2019 до 4/4/2019.

Prod1 имеет 1 отсутствующую дату - 4/2/2019.

Я хотел бы найти отсутствующие даты для всех ProdID и заполнить Val1-3 данными, скопированными из последней из предыдущих записей.Например, я хотел бы скопировать данные из 4/1/2019 в 4/2/2019

ProdID  Date        Val1 Val2 Val3
Prod1   4/1/2019    1    3    4
Prod1   4/2/2019    1    3    4
Prod1   4/3/2019    2    3    54
Prod1   4/4/2019    3    4    54
Prod2   4/1/2019    1    3    3
Prod2   4/2/2019    1    3    4
Prod2   4/3/2019    2    4    4
Prod2   4/4/2019    2    5    3

Ответы [ 2 ]

5 голосов
/ 09 апреля 2019

Сначала преобразуйте столбец в datetime с на to_datetime, затем создайте DatetimeIndex на DataFrame.set_index и вызовите GroupBy.apply с помощью DataFrame.asfreq - также можно указать метод для пропущенных значений прямого или обратного заполнения:

df['Date'] = pd.to_datetime(df['Date'])

df1 = (df.set_index('Date')
         .groupby('ProdID')
         .apply(lambda x: x.asfreq('D', method='ffill'))
         .reset_index(level=0, drop=True)
         .reset_index()
         .reindex(df.columns, axis=1))

print (df1)
  ProdID       Date  Val1  Val2  Val3
0  Prod1 2019-04-01     1     3     4
1  Prod1 2019-04-02     1     3     4
2  Prod1 2019-04-03     2     3    54
3  Prod1 2019-04-04     3     4    54
4  Prod2 2019-04-01     1     3     3
5  Prod2 2019-04-02     1     3     4
6  Prod2 2019-04-03     2     4     4
7  Prod2 2019-04-04     2     5     3

Другим решением является создание всех комбинаций продукта и datetimes с помощью product и DataFrame.merge с левым объединением, последним заполнением пропущенных значений на ffill:

dates = pd.date_range(start=df['Date'].min(), end=df['Date'].max())
prods = df.ProdID.unique()

from  itertools import product
df1 = pd.DataFrame(list(product(prods, dates)), columns=['ProdID', 'Date'])
print (df1)
  ProdID       Date
0  Prod1 2019-04-01
1  Prod1 2019-04-02
2  Prod1 2019-04-03
3  Prod1 2019-04-04
4  Prod2 2019-04-01
5  Prod2 2019-04-02
6  Prod2 2019-04-03
7  Prod2 2019-04-04

df = df1.merge(df, how='left').ffill()
print (df)
  ProdID       Date  Val1  Val2  Val3
0  Prod1 2019-04-01   1.0   3.0   4.0
1  Prod1 2019-04-02   1.0   3.0   4.0
2  Prod1 2019-04-03   2.0   3.0  54.0
3  Prod1 2019-04-04   3.0   4.0  54.0
4  Prod2 2019-04-01   1.0   3.0   3.0
5  Prod2 2019-04-02   1.0   3.0   4.0
6  Prod2 2019-04-03   2.0   4.0   4.0
7  Prod2 2019-04-04   2.0   5.0   3.0
0 голосов
/ 09 апреля 2019

Вы также можете использовать pandas.MultiIndex.from_product, DataFrame.reindex и DataFrame.ffill следующим образом:

df['Date'] = pd.to_datetime(df['Date'])
dates = pd.date_range(start=df.Date.min(), end=df.Date.max(), freq='1D')

idx = pd.MultiIndex.from_product([df.ProdID.unique(), dates], names=['ProdID', 'Date'])

df.set_index(['ProdID', 'Date']).reindex(idx).ffill().reset_index()

[output]

  ProdID       Date  Val1  Val2  Val3
0  Prod1 2019-04-01   1.0   3.0   4.0
1  Prod1 2019-04-02   1.0   3.0   4.0
2  Prod1 2019-04-03   2.0   3.0  54.0
3  Prod1 2019-04-04   3.0   4.0  54.0
4  Prod2 2019-04-01   1.0   3.0   3.0
5  Prod2 2019-04-02   1.0   3.0   4.0
6  Prod2 2019-04-03   2.0   4.0   4.0
7  Prod2 2019-04-04   2.0   5.0   3.0
...