【问题标题】:Roll data forward in python keeping the days consistent在 python 中前滚数据,保持日期一致
【发布时间】:2021-02-04 22:47:53
【问题描述】:

我有一组保持不变的数据。我还没有确定存储它的最佳格式,可能是 DataFrame,但我愿意接受建议。

我的目标是向前滚动数据,因此我的静态数据集是最新的,但我需要保持日期一致。例如,如果我的静态数据如下所示:


         Date  Day Temp
0  01/01/2021  Fri   20
1  02/01/2021  Sat   17
2  03/01/2021  Sun   17
3  04/01/2021  Mon   16
4  05/01/2021  Tue   20
5  06/01/2021  Wed   16
6  07/01/2021  Thu   21
7  08/01/2021  Fri   19

我将拥有的最后一个数据是 08/01/2021。如果我要在 2021 年 9 月 1 日运行这些数据,它看起来像:


Date  Day Temp
0  02/01/2021  Sat   17
1  03/01/2021  Sun   17
2  04/01/2021  Mon   16
3  05/01/2021  Tue   20
4  06/01/2021  Wed   16
5  07/01/2021  Thu   21
6  08/01/2021  Fri   19
7  09/01/2021  Sat   17

09/01/2021 是星期六,因此它将数据集中上一个星期六的数据向前滚动,即 02/01/2021。

我无法提前确定数据集将包含多少天,并且我可能必须多次前滚数据,例如,静态数据集中的最后一个数据可能是 15/05/ 2018 年,我需要把它延续到今天。

我看过 numpy roll 和 pandas shift,但我很难让日子保持一致。

出于兴趣,可以进一步改进这一点。它不是匹配最早的日期并将其向前滚动,而是首先尝试匹配具有相同月份和日期的最旧数据 - 以便每月温度保持一致?

谢谢

【问题讨论】:

  • 出于好奇,为什么要根据星期几保持温度不变?温度通常每天在每月平均值附近变化,而每月平均值在一年中变化(即 1 月与 6 月的平均温度)?
  • 嗨,@itprorh66。这就是我试图通过匹配相同的月份和日期来实现的目标 - 除非你认为这行不通?

标签: python python-3.x pandas date


【解决方案1】:

如果不能保证静态数据具有连续日期等,您可以使用groupby 来匹配星期几和月份的最后一条记录。如果一周中的那一天没有任何数据匹配,这将给出KeyError

这是您的初始 df:

df = pd.DataFrame({'Date': {0: pd.to_datetime('2021-01-01'),
1: pd.to_datetime('2021-01-02'),
2: pd.to_datetime('2021-01-03'), 
3: pd.to_datetime('2021-01-04'),
4: pd.to_datetime('2021-01-05'),
5: pd.to_datetime('2021-01-06'),
6: pd.to_datetime('2021-01-07'),
7: pd.to_datetime('2021-01-08')},
'Day': {0: 'Fri',  1: 'Sat',  2: 'Sun', 3: 'Mon', 
         4: 'Tue', 5: 'Wed', 6: 'Thu', 7: 'Fri'},
 'Temp': {0: 20, 1: 17, 2: 17, 3: 16, 4: 20, 
          5: 16, 6: 21, 7: 19}})

如果您想取消第一条记录,您可以通过多种方式进行...这使用 shift(),尽管这会使 df['Temp'] 列因为 NaN 而成为浮点数,如果这很重要的话。

df = df.shift(-1).dropna()

下一部分根据您的静态数据构建查找表。

  • 第一个按月份和星期几进行索引,并保留每对的最新值——我认为这就是你想要的。如果您确实想要最早的日期,只需使用 first 而不是 last
  • 第二个 lookup2 删除月份索引并为您提供数据以获取最近匹配的 day_of_week,忽略月份。

代码:

lookup = df.groupby([df['Date'].dt.month, df['Date'].dt.day_of_week]).last()
lookup2 = lookup.droplevel(0)
lookup2 = lookup2[~lookup2.index.duplicated(keep='last')]

插入记录的代码如下。我将它包含在一个循环中,每次都添加第二天,这样您就可以连续添加多天来测试它:

ndays = 5
for i in range(ndays):
    next_date = df.iloc[-1]['Date'] + pd.Timedelta("1D")
    try:
        temp = lookup.loc[(next_date.month, next_date.day_of_week), 'Temp']
    except KeyError:
        temp = lookup2.loc[next_date.day_of_week, 'Temp']
    df = df.append( {'Date' : next_date, 'Day' : next_date.strftime("%a"), 'Temp' : temp}, ignore_index=True)

print(df)
         Date  Day  Temp
0  2021-01-02  Sat  17.0
1  2021-01-03  Sun  17.0
2  2021-01-04  Mon  16.0
3  2021-01-05  Tue  20.0
4  2021-01-06  Wed  16.0
5  2021-01-07  Thu  21.0
6  2021-01-08  Fri  19.0
7  2021-01-09  Sat  17.0
8  2021-01-10  Sun  17.0
9  2021-01-11  Mon  16.0
10 2021-01-12  Tue  20.0
11 2021-01-13  Wed  16.0

无论如何,希望这至少符合您的要求,并且您可以对其进行修改以满足您的需求。

【讨论】:

  • 嗨@rick-m,我想这可以让我继续前进,谢谢。一个简单的问题,我收到 AttributeError 的错误消息:'Timestamp' object has no attribute 'day_of_week'。如果我用 dt.day_name() 替换 dt.day_of_week 是否有效?
  • 我认为您使用 timestamp..weekday() 方法访问“day_of_week”。
  • 嗯。发布的代码对我有用,没有错误。我正在运行 pandas 1.2.1 版...也许可以尝试将“day_of_week”更改为“dayofweek”,因为那是 added in 1.2.0
【解决方案2】:
df['Date']=pd.to_datetime(df['Date'], format='%d/%m/%Y')+ pd.Timedelta('1 day')#Roll day forward
df['Day']=df['Date'].dt.strftime('%a')#Extract Day Name from Date
#df['Temp']=df['Temp'].shift(-1).fillna(df['Temp'].shift())#Should have been ideal?
df['Temp']=df['Temp'].shift(-1).fillna(df['Temp'].shift(5))#Fillna of the last row




    Date  Day  Temp
0 2021-01-02  Sat  17.0
1 2021-01-03  Sun  17.0
2 2021-01-04  Mon  16.0
3 2021-01-05  Tue  20.0
4 2021-01-06  Wed  16.0
5 2021-01-07  Thu  21.0
6 2021-01-08  Fri  19.0
7 2021-01-09  Sat  17.0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2017-10-14
    • 2015-09-03
    相关资源
    最近更新 更多