Pandas DataFrame:将数据扩展到整月

Pandas DataFrame: expanding data to full month

我得到了每月时间跟踪预订的数据。由于没有周末和国定假日的预订,因此数据缺失了几天。现在我正在扩展数据,以便它包括该月的所有日期,但只包含空数据。这就是我解决它的方法。不知道有没有更优雅的方法来实现同样的事情?

为列 start 编制索引的样本输入数据:

+---------------------+--------+-------+----------+-----------------+---------+
| start               | from   | to    | paused   |   hours_working |   error |
|---------------------+--------+-------+----------+-----------------+---------|
| 2019-11-04 00:00:00 | 08:30  | 18:00 | 00:30    |               9 |       0 |
| 2019-11-05 00:00:00 | 09:30  | 19:00 | 00:30    |               9 |       0 |
| 2019-11-06 00:00:00 | 09:00  | 18:00 | 01:00    |               8 |       0 |
+---------------------+--------+-------+----------+-----------------+---------+

然后我检索第一个时间戳,然后用它来为整个月创建 period/index:

# get first day of the month
first_timestamp = df.index[0].replace(day=1).strftime("%Y-%m-%d")

# build an index containing all days of that month
index_month = pd.date_range(start=first_timestamp, periods=pd.Period(first_timestamp).days_in_month, freq="24H")
index_month

导致:

DatetimeIndex(['2019-11-01', '2019-11-02', '2019-11-03', '2019-11-04',
               '2019-11-05', '2019-11-06', '2019-11-07', '2019-11-08',
               '2019-11-09', '2019-11-10', '2019-11-11', '2019-11-12',
               '2019-11-13', '2019-11-14', '2019-11-15', '2019-11-16',
               '2019-11-17', '2019-11-18', '2019-11-19', '2019-11-20',
               '2019-11-21', '2019-11-22', '2019-11-23', '2019-11-24',
               '2019-11-25', '2019-11-26', '2019-11-27', '2019-11-28',
               '2019-11-29', '2019-11-30'],
              dtype='datetime64[ns]', freq='24H')

不幸的是,我不知道如何将索引(日期范围)与原始数据连接起来。因此,我必须使用新索引创建一个新的空数据框,并将该数据框与原始数据连接起来。

df_index = pd.DataFrame(index_month, columns=['start'])
df_index.set_index('start', inplace=True)

df_month = df_index.join(df).reset_index()

from tabulate import tabulate
print(tabulate(df_month, headers='keys', tablefmt='psql'))

给我最终结果:

+----+---------------------+--------+-------+----------+-----------------+---------+
|    | start               | from   | to    | paused   |   hours_working |   error |
|----+---------------------+--------+-------+----------+-----------------+---------|
|  0 | 2019-11-01 00:00:00 | nan    | nan   | nan      |             nan |     nan |
|  1 | 2019-11-02 00:00:00 | nan    | nan   | nan      |             nan |     nan |
|  2 | 2019-11-03 00:00:00 | nan    | nan   | nan      |             nan |     nan |
|  3 | 2019-11-04 00:00:00 | 08:30  | 18:00 | 00:30    |               9 |       0 |
|  4 | 2019-11-05 00:00:00 | 09:30  | 19:00 | 00:30    |               9 |       0 |
|  5 | 2019-11-06 00:00:00 | 09:00  | 18:00 | 01:00    |               8 |       0 |
|  6 | 2019-11-07 00:00:00 | nan    | nan   | nan      |             nan |     nan |
|  7 | 2019-11-08 00:00:00 | nan    | nan   | nan      |             nan |     nan |
|  8 | 2019-11-09 00:00:00 | nan    | nan   | nan      |             nan |     nan |
|  9 | 2019-11-10 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 10 | 2019-11-11 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 11 | 2019-11-12 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 12 | 2019-11-13 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 13 | 2019-11-14 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 14 | 2019-11-15 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 15 | 2019-11-16 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 16 | 2019-11-17 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 17 | 2019-11-18 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 18 | 2019-11-19 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 19 | 2019-11-20 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 20 | 2019-11-21 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 21 | 2019-11-22 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 22 | 2019-11-23 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 23 | 2019-11-24 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 24 | 2019-11-25 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 25 | 2019-11-26 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 26 | 2019-11-27 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 27 | 2019-11-28 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 28 | 2019-11-29 00:00:00 | nan    | nan   | nan      |             nan |     nan |
| 29 | 2019-11-30 00:00:00 | nan    | nan   | nan      |             nan |     nan |
+----+---------------------+--------+-------+----------+-----------------+---------+

那么,这有什么问题吗?没什么,结果还好。但是我想知道是否有更好的方法来为那个月创建索引,然后如何将索引与原始数据连接起来?有什么建议么?只想学习并变得更好 ;)

如果 DatetimeIndex 的所有值都是唯一的,这里可以使用 DataFrame.reindex - also for start and end of new DatetimeIndex is first convert first value to month Period and then used Period.to_timestamp:

first_per = df.index[0].to_period('m')

# build an index containing all days of that month
index_month = pd.date_range(start=first_per.to_timestamp(how='start'), 
                            end=first_per.to_timestamp(how='end'),
                            freq="24H",
                            name='start')

df = df.reindex(index_month).reset_index()
print (df.head(10))
       start   from     to paused  hours_working  error
0 2019-11-01    NaN    NaN    NaN            NaN    NaN
1 2019-11-02    NaN    NaN    NaN            NaN    NaN
2 2019-11-03    NaN    NaN    NaN            NaN    NaN
3 2019-11-04  08:30  18:00  00:30            9.0    0.0
4 2019-11-05  09:30  19:00  00:30            9.0    0.0
5 2019-11-06  09:00  18:00  01:00            8.0    0.0
6 2019-11-07    NaN    NaN    NaN            NaN    NaN
7 2019-11-08    NaN    NaN    NaN            NaN    NaN
8 2019-11-09    NaN    NaN    NaN            NaN    NaN
9 2019-11-10    NaN    NaN    NaN            NaN    NaN