【问题标题】:Rearrangment of time series data时间序列数据的重新排列
【发布时间】:2018-01-13 08:06:04
【问题描述】:

我不擅长“R”,不知道如何重新排列和子集时间序列数据。对不起,如果这个问题听起来很愚蠢。 我有一个海潮时间序列数据,每天有四个值(也有缺失值)。两个涨潮值和两个低潮值。时间和日期在同一列但在不同的行中给出。现在,我只想为白天(从早上 7:00 到晚上 7:00)而不是晚上的数据子集。然后我只想将数据排列在三列中,i)日期,ii)时间和 iii)潮汐。对于 Tide,我只需要最小值和最大值。这是数据和所需数据排列的示例。对于每个日期,数据按示例排列成三行。

1/1/2011    Low High    Low NA
Time    2:58 AM 9:38 AM 5:19 PM NA
Tide    1.2 m   2.2 m   0.6 m   NA
1/2/2011    High    Low High    Low
Time    2:07 AM 4:22 AM 10:19 AM    6:07 PM
Tide    1.4 m   1.3 m   2.3 m   0.4 m

Date    Time    Tide
1/1/2011    17:19   0.6
1/1/2011    9:38    2.2
1/2/2011    2:07    1.4
1/2/2011    18:07   0.4

【问题讨论】:

  • 出于好奇,您从哪里获取数据?了解这一点可能有助于确保任何解决方案都是稳健的,即,将适用于未来的数据拉取。
  • @Woodstock,此数据来自阿布扎比。数据是 12 年的,因此需要处理大量数据。

标签: r sorting time-series subset


【解决方案1】:

如果列表不太长,只需通过映射单元格和过滤,在电子表格中完成这项工作会更简单。但是在 R 中使用 zoo 和 tidyverse 的一种方法如下:

假设原始数据框的列名为 C1:C5

        C1      C2      C3       C4      C5
     <chr>   <chr>   <chr>    <chr>   <chr>
1 1/1/2010     Low    High      Low    <NA>
2     Time 2:58 AM 9:38 AM  5:19 PM    <NA>
3     Tide     1.2     2.2      0.6    <NA>
4 1/2/2011    High     Low     High     Low
5     Time 2:07 AM 4:22 AM 10:19 AM 6:07 PM
6     Tide     1.4     1.3      2.3     0.4

DF <- DF %>% 
        mutate(Date = as.Date(gsub("Tide|Time","", C1), format = "%d/%m/%Y"))
DF <- DF %>% 
        mutate(Date = na.locf(DF$Date, na.rm = TRUE),
                        C1 = gsub("[[:digit:]]|\\/", "", C1),
                        Type = if_else(nchar(C1) == 0, "TideType", C1)) %>% 
              select(Date, Type, C2:C5) %>% 
              gather(oColumn, Value, -c(Date, Type)) %>%
              spread(key = Type, value = Value) %>% 
              select(Date, Time, Tide) %>%
              filter(complete.cases(.))
DF <- DF %>% 
         mutate(Time = ymd_hm(paste(DF$Date, DF$Time, sep = " ")),
                Tide = as.numeric(Tide))
DF <- DF %>% 
         mutate(DayNight = (DF$Time) %within% 
          interval(as.POSIXlt(DF$Date) + (7*60*60), as.POSIXlt(DF$Date) + (19*60*60))) %>% 
        filter(DayNight == TRUE) %>%
        select(-DayNight) ) %>%
        group_by(Date) %>%
        filter(Tide == max(Tide) | min(Tide))

DF
Source: local data frame [4 x 3]
Groups: Date [2]

        Date                Time  Tide
      <date>              <dttm> <dbl>
1 2010-01-01 2010-01-01 09:38:00   2.2
2 2010-01-01 2010-01-01 17:19:00   0.6
3 2011-02-01 2011-02-01 10:19:00   2.3
4 2011-02-01 2011-02-01 18:07:00   0.4

请注意,“Date”是 Date 类型的 Object,“Time”是 Posixct 类型的 Date-Time 对象。您可能希望将“时间”转换为分钟向量。

【讨论】:

    【解决方案2】:

    假设输入DF 与以下注释中的内容相同。

    g,分组向量,DF 每行有一个元素,等于c(1, 1, 1, 2, 2, 2, ...)。计算g 的替代方法是n &lt;- nrow(DF); g &lt;- gl(n, 3, n)n &lt;- nrow(DF); g &lt;- rep(1:3, n, n)

    然后我们使用byDF 拆分为组,并将指定的匿名函数应用于g 定义的每个组。

    匿名函数结合当前组中的日期和时间创建日期/时间dt,利用公共日期为x[1,1]且被清理之前的时间在@987654333 @。 使用dtx[2, -1] 中的潮汐(在被清理之前),它计算将它们排列成数据框的三列中的每一列。然后有一个注释掉的行,它删除了 NA 值。如果你想要这个取消注释它。将到目前为止获得的数据帧设置为早上 7 点到晚上 7 点的时间段,并进一步获取由最小和最大潮汐组成的两行。我们按时间排序。

    最后do.call("rbind", ...) 将这些组放在一个整体数据框中。

    没有使用任何包。

    g <- cumsum(grepl("\\d", DF$V1))
    Long <- do.call("rbind", by(DF, g, function(x) {
      dt <- as.POSIXct(paste(x[1,1], as.matrix(x[2, -1])), format = "%m/%d/%Y %I:%M %p")
      X <- data.frame(Date = as.Date(dt),
                      Time = format(dt, "%H:%M"),
                      Tide = as.numeric(sub("m", "", as.matrix(x[3, -1]))),
                      stringsAsFactors = FALSE)
      # X <- na.omit(X)
      X <- subset(X, Time >= "07:00" & Time <= "19:00")
      X <- X[c(which.min(X$Tide), which.max(X$Tide)), ]
      X[order(X$Time), ]
    }))
    

    给出以下内容 - 请注意,问题输出中的第三行不在上午 7 点和晚上 7 点之间,因此此处的输出必然不同。

    > Long
              Date  Time Tide
    1.2 2011-01-01 09:38  2.2
    1.3 2011-01-01 17:19  0.6
    2.3 2011-01-02 10:19  2.3
    2.4 2011-01-02 18:07  0.4
    

    注意:输入DF被假定为可重现形式如下:

    Lines <- "1/1/2011,Low,High,Low,NA
    Time,2:58 AM,9:38 AM,5:19 PM,NA
    Tide,1.2 m,2.2 m,0.6 m,NA
    1/2/2011,High,Low,High,Low
    Time,2:07 AM,4:22 AM,10:19 AM,6:07 PM
    Tide,1.4 m,1.3 m,2.3 m,0.4 m"
    DF <- read.table(text = Lines, sep = ",", as.is = TRUE)
    

    【讨论】:

    • 我正在努力跟随你所做的。剪切并粘贴您的代码,我的输出的第二行为 1.3 2011-01-02 17:19 0.6 --> 请注意这是 1 月 2 日,而不是 1 月 1 日...我在某个地方搞砸了吗?
    • 开始一个新的 R 会话,复制并粘贴注释中的代码以生成输入,然后将代码复制并粘贴到答案本身以获得结果。这应该与答案中显示的结果相匹配。
    猜你喜欢
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多