【问题标题】:How to calculate and extract prices from timestamps in R如何从 R 中的时间戳计算和提取价格
【发布时间】:2021-08-24 17:39:43
【问题描述】:

我有商品价格数据,如下表所示:

Date      Time         Price
19990104  14:11:14.34  220 
19990104  14:11:21.21  200 
19990104  14:11:36.35  221  
19990104  14:11:45.45  202  
19990104  14:11:56.11  215  

您看到时间是 14h 11m 和 x 秒,其中 .xx 毫秒。我试图找到一分钟内给出的第一个值、最后一个值、最高和最低值。我有数千天和数千分钟的数据,以上只是摘录。

因此,我想创建一个包含所有信息的行。 对于上面的表格,结果应该是:

Date     Time      Start End  Low High
19990104 14:11:00  220   215  200 221   

感谢任何帮助。谢谢!

【问题讨论】:

    标签: r dataframe calculated-columns calculation


    【解决方案1】:

    首先,将DateTime 字段转换为单个POSIXt 类对象可能是更好的方法。如果您需要 Date+Time 在某些时候成为类似数字的字段(例如,随着时间的推移绘制一些东西),这将是一个好方法。这不是必需的,但根据我的经验,我几乎总是需要用数字来处理时间(日期通常也需要在那里)。

    如果您不想/不需要更改为 POSIXtTime 课程,您可以执行以下操作。 (我添加了几个数据行以显示多个汇总行。)

    基础 R

    dat$min <- substr(dat$Time, 1, 5)
    aggregate(dat$Price, dat[,c("Date","min")], function(Price) c(Start=Price[1], End=Price[length(Price)], Low=min(Price), High=max(Price)))
    #       Date   min x.Start x.End x.Low x.High
    # 1 19990104 14:11     220   215   200    221
    # 2 19990104 14:12     229   209   209    229
    

    dplyr

    library(dplyr)
    dat %>%
      arrange(Date, Time) %>%
      group_by(Date, min = substr(dat$Time, 1, 5)) %>%
      summarize(Time = min(Time), Start = first(Price), End = last(Price), Low = min(Price), High = max(Price)) %>%
      ungroup() %>%
      select(-min)
    # # A tibble: 2 x 6
    #       Date Time     Start   End   Low  High
    #      <int> <chr>    <int> <int> <int> <int>
    # 1 19990104 14:11:14   220   215   200   221
    # 2 19990104 14:12:14   229   209   209   229
    

    数据

    dat <- structure(list(Date = c(19990104L, 19990104L, 19990104L, 19990104L, 19990104L, 19990104L, 19990104L), Time = c("14:11:14", "14:11:21", "14:11:36", "14:11:45", "14:11:56", "14:12:14", "14:12:21"),     Price = c(220L, 200L, 221L, 202L, 215L, 229L, 209L)), class = "data.frame", row.names = c(NA, -7L))
    

    【讨论】:

      【解决方案2】:
      1. 首先从您的示例中创建数据框 (d)
      2. 然后,使用正则表达式提取小时、分钟和秒
      3. 最后,对分组和排列的数据使用 summarise() 以获得您想要的输出
      library(tibble)
      library(dplyr)
      
      d <- tribble(
        ~Date,      ~Time,      ~Price,
        19990104,  "14:11:14",  220, 
        19990104,  "14:11:21",  200, 
        19990104,  "14:11:36",  221,  
        19990104,  "14:11:45",  202,  
        19990104,  "14:11:56",  215 
      )
      
      
      d %>%
        mutate(hour = gsub("^([0-9]{2}):.*$", "\\1", Time),
               minute = gsub("^.*:([0-9]{2}):.*$", "\\1", Time),
               seconds = gsub("^.*:.*:([0-9]{2})$", "\\1", Time),
               totalseconds = (as.numeric(hour) * 60 * 60) + (as.numeric(minute) * 60) + as.numeric(seconds)) %>%
        group_by(Date, hour, minute) %>%
        arrange(Date, hour, minute, seconds) %>%
        summarize(Start = first(Price),
                  End = last(Price),
                  Low = min(Price),
                  High = max(Price)) %>%
        mutate(Time = paste0(hour, ":", minute, ":00")) %>%
        select(-hour, -minute) %>%
        relocate(Time, .before = Start)
      

      【讨论】:

        【解决方案3】:

        这个怎么样:

        dat <- tibble::tribble(
          ~Date,      ~Time,      ~Price,
        19990104,  "14:11:14", 220, 
        19990104,  "14:11:21",  200, 
        19990104,  "14:11:36", 221,  
        19990104,  "14:11:45",  202 , 
        19990104,  "14:11:56", 215)  
        
        library(lubridate)
        library(dplyr)
        
        dat %>% 
          mutate(hms = hms(Time), 
                 hour = hour(hms), 
                 minute = minute(hms), 
                 Time = hm(paste(hour, minute, sep=":"))) %>% 
          group_by(Date, Time) %>% 
          summarise(Start = first(Price), 
                    End = last(Price), 
                    Low = min(Price), 
                    High = max(Price)) 
        
        # `summarise()` has grouped output by 'Date'. You can override using the `.groups` argument.
        # # A tibble: 1 x 6
        # # Groups:   Date [1]
        #       Date Time       Start   End   Low  High
        #      <dbl> <Period>   <dbl> <dbl> <dbl> <dbl>  
        # 1 19990104 14H 11M 0S   220   215   200   221
        

        【讨论】:

        • 感谢您对迟到的回复感到抱歉!代码有效,但我在一开始的示例中犯了一个小错误,如您在上面看到的那样,我已经更改了它。我有一个像14:11:05.23 这样的时间。因此,我不仅有秒数,还有毫秒数,但我想要与您的解决方案中相同的输出。删除毫秒并有 0 秒。你有什么想法吗?
        【解决方案4】:

        to.minutes 在 quantmod 包中执行此操作。假设 DF 在最后的注释中重复显示,将其转换为动物园对象,使用 to.minutes 执行所需的计算,给出 zm 并将分钟向下舍入给出 zm0。最后,我们使用fortify.zoo 将其转换为数据框;但是,您可能希望将其保留为 zm0 以简化使用 quantmod 和 zoo 的其他工具。请注意,quantmod 提供了提取函数:Hi、Lo、Op 和 Cl,还提供了绘制 OHLC 级数的函数。

        library(quantmod) # also loads zoo 
        library(lubridate)
        
        # this requires R 4.1.  Replace \ with the word function if
        #   you have an old version of R    
        z <- read.zoo(DF, index = 1:2, FUN = \(d, t) ymd_hms(paste(d, t)))
        
        zm <- to.minutes(z)
        zm0 <- aggregate(zm, floor_date(time(zm), "min"))
        
        DF2 <- fortify.zoo(zm0); DF2
        ##                 Index z.Open z.High z.Low z.Close
        ## 1 1999-01-04 14:11:00    220    221   200     215
        
        Cl(DF2)
        ## [1] 215
        

        使用的版本

        R.version.string
        ## [1] "R version 4.1.1 Patched (2021-08-10 r80733)"
        
        packageVersion("quantmod")
        ## [1] ‘0.4.18’
        
        packageVersion("zoo")
        ## [1] ‘1.8.9’
        
        packageVersion("lubridate")
        ## [1] ‘1.7.10’
        

        注意

        Lines <- "Date      Time      Price
        19990104  14:11:14  220 
        19990104  14:11:21  200 
        19990104  14:11:36  221  
        19990104  14:11:45  202  
        19990104  14:11:56  215  "
        
        DF <- read.table(text = Lines, header = TRUE)
        

        【讨论】:

        • 谢谢您的回答...我很不确定z &lt;- read.zoo(DF, index = 1:2, FUN = \(d, t) ymd_hms(paste(d, t))) 是什么意思这里的索引是什么,FUN 是什么意思?收到消息:“z 中出现意外输入错误”
        • 动物园对象是一个向量或矩阵,其属性给出时间索引并具有“动物园”类。 read.zoo 使用DF 的前两列将DF 转换为具有POSIXct 时间索引的动物园系列以创建该索引。有关更多信息,请参阅?read.zoo 和 zoo 附带的 5 个小插曲和参考手册。其中一个小插曲完全集中在read.zoo 上。
        • Note 中的数据没有给出错误,因此您一定在某处引入了错误,但不知道您做了什么,很难解决。
        • 谢谢,但括号中的 d, t 是我需要使用的值还是我必须将自己的值放在那里?
        • 使用DF &lt;- structure(list(Date = c(19990104L, 19990104L, 19990104L, 19990104L, 19990104L), Time = c("14:11:14.34", "14:11:21.21", "14:11:36.35", "14:11:45.45", "14:11:56.11"), Price = c(220L, 200L, 221L, 202L, 215L)), class = "data.frame", row.names = c(NA, -5L)),答案中的代码仍然有效。
        【解决方案5】:

        dplyr 包应该可以在这里为您提供帮助。假设数据首先按日期和时间排序,下面这段代码应该能够按照您想要的方式对数据进行分组:

        library(dplyr)
        
        data = data.frame(Date = rep("19990104", 5),
                          Time = c("14:11:14", "14:11:21", "14:11:36", "14:11:45", "14:11:56"),
                          Price = c(220, 200, 221, 202, 215),
                          stringsAsFactors = F)
        
        
        data_processed = data %>%
          dplyr::mutate(Time_min = paste(substr(Time, start = 1, stop = 5), "00", sep = ":"))
        
        data_summary <- data_processed %>%
          dplyr::group_by(Date, Time_min) %>%
          dplyr::summarise(Start = dplyr::first(Price),
                           End = dplyr::last(Price),
                           Low = min(Price, na.rm = T),
                           High = max(Price, na.rm = T))
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-01
          • 2021-03-26
          • 2021-10-27
          • 1970-01-01
          • 2015-09-25
          • 1970-01-01
          相关资源
          最近更新 更多