完成一个稀疏的时间表

completing a sparse timeline

随着时间的推移,我对进程状态进行了一些稀疏的测量,如下所示:

               tag
2022-01-15  
2022-01-08  #Step3
2022-01-06  #Step2
2021-12-31  
2021-12-28  #Step1

...我想将它们转换成一个完整的系列,我可以用它来绘制时间线,如下所示:

               tag
2021-12-28  #Step1
2021-12-29  #Step1
2021-12-30  #Step1
2021-12-31  #Step1
2022-01-01  #Step1
2022-01-02  #Step1
2022-01-03  #Step1
2022-01-04  #Step1
2022-01-05  #Step1
2022-01-06  #Step2
2022-01-07  #Step2
2022-01-08  #Step3
2022-01-09  #Step3
2022-01-10  #Step3
2022-01-11  #Step3
2022-01-12  #Step3
2022-01-13  #Step3
2022-01-14  #Step3
2022-01-15  #Step3

下面的代码有效,但它看起来很丑陋,我想知道是否有更多 elegant/efficient 的方法来实现这一点。 另外,我得到一个 SettingWithCopyWarning,我应该可以修复它。

谢谢!!

#! /usr/bin/env python3

import pandas as pd


MY_SAMPLINGS = [
    {'timestamp': '2022-01-15', 'tag': ''}, 
    {'timestamp': '2022-01-08', 'tag': '#Step3'}, 
    {'timestamp': '2022-01-06', 'tag': '#Step2'}, 
    {'timestamp': '2021-12-31', 'tag': ''}, 
    {'timestamp': '2021-12-28', 'tag': '#Step1'}
    ]


myDates = [d['timestamp'] for d in MY_SAMPLINGS]
dates = pd.date_range(myDates[-1],myDates[0])
df = pd.DataFrame(index=dates, columns=['tag'])


for x in range((len(MY_SAMPLINGS)-1),0,-1): 
    startTime = MY_SAMPLINGS[x]['timestamp']
    endTime = MY_SAMPLINGS [x-1]['timestamp']
    if (MY_SAMPLINGS[x]['tag']):
        myTag = MY_SAMPLINGS[x]['tag']
    else:
        myTag = MY_SAMPLINGS[x+1]['tag']
    df.loc[startTime:endTime]['tag'] = myTag

print (df)

好吧,我会逐步分解所有内容,但这只是几行代码,而且比循环更具可扩展性。

import pandas as pd 

df = pd.DataFrame(MY_SAMPLINGS)

我们首先要将时间戳作为有序时间索引。

df["timestamp"] = pd.to_datetime(df["timestamp"], format="%Y-%m-%d")
df = df.set_index("timestamp").sort_index()

给出:

               tag
timestamp
2021-12-28  #Step1
2021-12-31
2022-01-06  #Step2
2022-01-08  #Step3
2022-01-15

然后,每天重采样并向前填充,这意味着重采样产生的任何缺失值将取前一个非缺失值的值。

df = df.resample("1D").ffill()

给出:

               tag
timestamp
2021-12-28  #Step1
2021-12-29  #Step1
2021-12-30  #Step1
2021-12-31
2022-01-01
2022-01-02
2022-01-03
2022-01-04
2022-01-05
2022-01-06  #Step2
2022-01-07  #Step2
2022-01-08  #Step3
2022-01-09  #Step3
2022-01-10  #Step3
2022-01-11  #Step3
2022-01-12  #Step3
2022-01-13  #Step3
2022-01-14  #Step3
2022-01-15

现在,我们仍然有所有那些空字符串,让我们再次将它们视为空和前向填充。

df = df.replace('', pd.NA).ffill()

现在我们完成了:

               tag
timestamp
2021-12-28  #Step1
2021-12-29  #Step1
2021-12-30  #Step1
2021-12-31  #Step1
2022-01-01  #Step1
2022-01-02  #Step1
2022-01-03  #Step1
2022-01-04  #Step1
2022-01-05  #Step1
2022-01-06  #Step2
2022-01-07  #Step2
2022-01-08  #Step3
2022-01-09  #Step3
2022-01-10  #Step3
2022-01-11  #Step3
2022-01-12  #Step3
2022-01-13  #Step3
2022-01-14  #Step3
2022-01-15  #Step3

你可以在这里尝试使用resample。请注意,我已经用 Nones 替换了一个空字符串,以便稍后我可以将 fillna 与 ffill 方法一起使用。

MY_SAMPLINGS = [
    {'timestamp': '2022-01-15', 'tag': None}, 
    {'timestamp': '2022-01-08', 'tag': '#Step3'}, 
    {'timestamp': '2022-01-06', 'tag': '#Step2'}, 
    {'timestamp': '2021-12-31', 'tag': None}, 
    {'timestamp': '2021-12-28', 'tag': '#Step1'}
    ]
df = pd.DataFrame(MY_SAMPLINGS).assign(timestamp=lambda x: pd.to_datetime(x["timestamp"])).set_index("timestamp")
result = df.resample('1D').pad().fillna(method="ffill")