• R语言python时间序列处理


    背景

    最近一个读者问到了这样的一个问题:

    1. 有一个时间序列的数据。
    2. 每半小时记录一次数据,但有的地方有缺失,时间序列不完整。
    3. 需要对缺失的部分,填充为NA。
    4. 也就是缺少的时间要加到表哥里面,缺失的值是要填充为NA

    好久没写R代码了,这里写一写吧。

    先创建一个样本

    library(tidyverse)
    
    
    sample_data = tibble('mytime'=c(
      lubridate::as_datetime("2022-01-01 12:30:00"),
      lubridate::as_datetime("2022-01-01 13:30:00"),
      lubridate::as_datetime("2022-01-01 14:00:00"),
      lubridate::as_datetime("2022-01-01 15:30:00")
    ),
    'value' = c(1,4,5,8),
    'value2' = c(3,4,5,6),
    'value3' = c(20, 20, 30, 40))
    
    sample_data
    
    # # A tibble: 4 × 4
    #   mytime              value value2 value3
    #                     
    # 1 2022-01-01 12:30:00     1      3     20
    # 2 2022-01-01 13:30:00     4      4     20
    # 3 2022-01-01 14:00:00     5      5     30
    # 4 2022-01-01 15:30:00     8      6     40
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    可以看出来上面的数据中:

    1. 数据的时间范围是从2022-01-01 12:302022-01-01 15:30的。
    2. 每隔30分钟就记录一次。
    3. 但是缺少了13:0014:3015:00时刻的数据。

    解决办法

    思路很简单:

    1. 就是创建一个连续的、每隔30分钟的、完整的时间列表。
    2. 然后把列表放到数据框里面。
    3. 然后使用left_join的特性,直接对表格进行关联即可,会自动填充NA

    1.创建连续的时间列表

    create_time_seq <- function(start_date, end_date, by){
      n = lubridate::interval(start = start_date, end = end_date) / by 
      
      res <- start_date + by * c(0:n)
      return(res)
      
    }
    
    time_seq <- create_time_seq(
      start_date = sample_data %>% pull(mytime) %>% min(),
      end_date = sample_data %>% pull(mytime) %>% max(),
      by = lubridate::minutes(30)
    )
    
    time_seq
    # [1] "2022-01-01 12:30:00 UTC" "2022-01-01 13:00:00 UTC" "2022-01-01 13:30:00 UTC"
    # [4] "2022-01-01 14:00:00 UTC" "2022-01-01 14:30:00 UTC" "2022-01-01 15:00:00 UTC"
    # [7] "2022-01-01 15:30:00 UTC"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这里的难点主要是在create_time_seq函数里面,这个函数的主要功能有:

    1. 这个函数计算了从开始时间结束时间,按照步长为by的时间节点的个数。
    2. 然后把这个范围内的节点都计算出来。保证一个节点都不少。

    最后time_seq就是按照样本数据的时间范围,和要求的步长,生成了一串符合要求的时间序列列表。

    2. 关联

    tibble(
      'true_time' = time_seq
    ) %>% left_join(
      y=sample_data,
      by=c('true_time' = 'mytime')
    )
    
    # # A tibble: 7 × 4
    #   true_time           value value2 value3
    #                     
    # 1 2022-01-01 12:30:00     1      3     20
    # 2 2022-01-01 13:00:00    NA     NA     NA
    # 3 2022-01-01 13:30:00     4      4     20
    # 4 2022-01-01 14:00:00     5      5     30
    # 5 2022-01-01 14:30:00    NA     NA     NA
    # 6 2022-01-01 15:00:00    NA     NA     NA
    # 7 2022-01-01 15:30:00     8      6     40
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    把列表放到数据框里面,然后巧妙的使用left_join函数,对两个表进行关联,从而对缺失的节点直接进行填充。

    总结

    1. 这个只是一个非常小的,对R语言的时间做处理的小案例。
    2. 建议大家在R中处理时间的时候,最好都用lubridate包来处理。
    3. 巧妙的生成时间序列、然后使用数据框来关联,这个思想在python里面也是常见的。如果用python写的话,其实就是使用列表推导式、datetime包、pandas包来做。

    我就知道你不信,我给你写过代码就知道了

    python版本

    # part1
    from datetime import datetime,timedelta
    import pandas as pd
    
    # part 2
    sample_date = pd.DataFrame({'mytime':[datetime.strptime(i,'%Y-%m-%d %X') for i in ['2022-01-01 12:30:00', '2022-01-01 13:30:00', '2022-01-01 14:00:00', '2022-01-01 15:30:00']],
                  'value1':[1,4,5,8], 'value2':[3,4,5,6], 'value3':[20, 20, 30, 40]})
    sample_date
    
    #                 mytime  value1  value2  value3
    # 0 2022-01-01 12:30:00       1       3      20
    # 1 2022-01-01 13:30:00       4       4      20
    # 2 2022-01-01 14:00:00       5       5      30
    # 3 2022-01-01 15:30:00       8       6      40
    
    # part 3
    def create_time_seq(start_date, end_date, by):
        n = (end_date - start_date ) / by
        res = [start_date + by * i for i in range(int(n+1))]
        return res
    
    time_seq = create_time_seq(start_date=sample_date['mytime'].min(),
                               end_date=sample_date['mytime'].max(),
                               by=timedelta(minutes=30))
    time_seq
    
    # [Timestamp('2022-01-01 12:30:00'), 
    # Timestamp('2022-01-01 13:00:00'), 
    # Timestamp('2022-01-01 13:30:00'), 
    # Timestamp('2022-01-01 14:00:00'), 
    # Timestamp('2022-01-01 14:30:00'), 
    # Timestamp('2022-01-01 15:00:00'), 
    # Timestamp('2022-01-01 15:30:00')]
    
    # part 4
    
    pd.DataFrame({'true_time':time_seq}).pipe(
        lambda x: x.merge(
            right=sample_date,
            how='left',
            left_on=['true_time'],
            right_on=['mytime']
        )
    ).pipe(
        lambda x: x.drop(columns=['mytime'])
    )
    
    #             true_time  value1  value2  value3
    # 0 2022-01-01 12:30:00     1.0     3.0    20.0
    # 1 2022-01-01 13:00:00     NaN     NaN     NaN
    # 2 2022-01-01 13:30:00     4.0     4.0    20.0
    # 3 2022-01-01 14:00:00     5.0     5.0    30.0
    # 4 2022-01-01 14:30:00     NaN     NaN     NaN
    # 5 2022-01-01 15:00:00     NaN     NaN     NaN
    # 6 2022-01-01 15:30:00     8.0     6.0    40.0
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    最终

    1. 没想到吧,学R的时候,竟然还学了PYTHON
    2. 有学习交流群,如果想加入本群的,想办法找到我~

    阅读更多

    list

  • 相关阅读:
    基于java+ssm幼儿园教学网站管理系统vue-计算机毕业设计
    疯狂Spring Boot讲义[推荐1]
    50ETF期权开户后需要多久才能交易?
    跨平台应用开发进阶(三十三) :Android上架准备材料及流程介绍
    VR全景广告——实体商家的营销新选择
    基于vue框架的uniapp小程序开发发现了新大陆
    结合卡尔曼滤波器和运动方程观测方程谈谈状态估计
    docker本地私有库和harbor仓库
    win10+visual studio 2022+itk+生成drr
    青少年python系列 43.导入类
  • 原文地址:https://blog.csdn.net/yuanzhoulvpi/article/details/126813238