时间序列数据的重新排列

时间:2017-08-05 14:08:18

标签: r sorting time-series subset

我不擅长“R”并且不确定如何重新排列和子集时间序列数据。对不起,如果这个问题听起来很愚蠢。 我有一个海潮的时间序列数据,每天有四个值(也有缺失值)。涨潮的两个值和退潮的两个值。时间和日期在同一列中给出,但在不同的行中。现在,我想仅将白天(从早上7点到晚上7点)的数据分组,而不是晚上。然后我想将数据排列在三列中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

2 个答案:

答案 0 :(得分:1)

输入DF假设如下面的注释中所示。

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

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

匿名函数结合当前组中的日期和时间来创建日期/时间dt,利用共同日期为x[1,1]的事实和清理之前的时间在x[2,-1]。  使用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 :(得分:0)

如果列表不是太长,那么只需通过映射单元格和过滤,就可以更容易地在电子表格中完成这项工作。但是在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”是Object的Date类型,“Time”是Date-Time Object的Posixct类型。您可能希望将“时间”转换为分钟向量。