5

我已经为此苦苦挣扎了一段时间。我是使用ts数据和所有相关 R 包的新手。我有一个带有几个变量的df,包括格林威治标准时间“%H%M”中的“一天中的时间”和发生采样的日期“%Y/%m/%e”。我想将我的日期数据分类/聚合为“周”(即 %W/%g),并计算在该周发生采样时的平均“一天中的时间”。

通过首先将我的 df 转换为 zoo 对象,然后使用如下所示的 aggregate.zoo 命令,我能够计算数值变量(例如重量)的其他乐趣:

#calculate the sum weight captured every week 
x2c <- aggregate(OA_zoo, as.Date(cut(time(OA_zoo), "week")), sum)

但是,我不确定如何解决我正在使用Date 格式而不是num的事实,并且不胜感激任何提示!此外,我显然已经通过分别处理我的每个变量来编码。是否有一种方法可以通过使用 plyr 聚合“每周”在我的 df 上应用不同的 FUN(总和/平均值/最大值/最小值)?还是其他一些包?

编辑/澄清dput是我的完整数据集样本的输出。我有 2004-2011 年的数据。我想使用 ggplot2 查看/绘制的是 TIME 的平均值/中位数(%H%M),在几周内随时间(2004-2011)聚合。现在,我的数据不是按周汇总的,而是每天汇总的(随机样本)。

> dput(godin)
structure(list(depth = c(878, 1200, 1170, 936, 942, 964, 951, 
953, 911, 969, 960, 987, 991, 997, 1024, 978, 1024, 951, 984, 
931, 1006, 929, 973, 986, 935, 989, 1042, 1015, 914, 984), duration = c(0.8, 
2.6, 6.5, 3.2, 4.1, 6.4, 7.2, 5.3, 7.4, 7, 7, 5.5, 7.5, 7.3, 
7.5, 7, 4.2, 3, 5, 5, 9.3, 7.9, 7.3, 7.2, 7, 5.2, 8, 6, 7.5, 
7), Greenland = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 40L, 28L, 0L, 
0L, 34L, 7L, 28L, 0L, 0L, 0L, 27L, 0L, 0L, 0L, 44L, 59L, 0L, 
0L, 0L, 0L, 0L, 0L), date2 = structure(c(12617, 12627, 12631, 
12996, 12669, 13036, 12669, 13036, 12670, 13036, 12670, 13037, 
12671, 13037, 12671, 13037, 12671, 13038, 12672, 13038, 12672, 
13038, 12672, 13039, 12631, 12997, 12673, 13039, 12673, 13039
), class = "Date"), TIME = c("0940", "0145", "0945", "2045", 
"1615", "0310", "2130", "1045", "0625", "1830", "1520", "0630", 
"0035", "1330", "0930", "2215", "2010", "0645", "0155", "1205", 
"0815", "1845", "2115", "0350", "1745", "0410", "0550", "1345", 
"1515", "2115")), .Names = c("depth", "duration", "Greenland", 
"date2", "TIME"), class = "data.frame", row.names = c("6761", 
"9019", "9020", "9021", "9022", "9023", "9024", "9025", "9026", 
"9027", "9028", "9029", "9030", "9031", "9032", "9033", "9034", 
"9035", "9036", "9037", "9038", "9039", "9040", "9041", "9042", 
"9043", "9044", "9045", "9046", "9047"))
4

3 回答 3

3

我会这样处理它:首先用一个代表星期的字符串创建一个列:

godin$week <- format(godin$date2, "%Y-W%U")

这会给你类似的东西"2004-W26",这已经足够了aggregate

那么您需要将表示 HHMM 的字符向量转换为实际时间,以便您可以在其上使用时间数学。

godin$time2 <- as.POSIXct(strptime(godin$TIME, "%H%M"))

注意:以上内容有点骇人听闻...strptime()如果未指定当前日期,则假定为当前日期,但这不应妨碍此特定应用程序,因为所有转换后的时间都将具有相同的日期,时间部分平均值是正确的。稍后我会删除日期...

那时,我认为您可以简单地汇总:

x2c <- aggregate(time2~week, data=godin, FUN=mean)

并摆脱不相关(和错误)的日期部分

x2c$time2 <- format(x2c$time2,"%H:%M:%S")

等瞧。

> x2c
      week    time2
1 2004-W29 09:40:00
2 2004-W30 01:45:00
3 2004-W31 13:45:00
4 2004-W36 12:07:00
5 2004-W37 10:32:30
6 2005-W31 12:27:30
7 2005-W36 10:48:20
8 2005-W37 13:11:06

这里的教训是,在 R 中推动没有相关日期的时间是很棘手的。我很想听听其他有更好方法的人的意见。

于 2012-07-17T17:52:38.470 回答
2

您需要将该TIME列转换为常用单位(即分钟)。这里有几个辅助函数可以做到这一点:

hour2min <- function(hhmm) {
  hhmm <- as.numeric(hhmm)
  trunc(hhmm/100)*60 + hhmm %% 100
}
min2hour <- function(min) {
  min <- as.numeric(min)
  trunc(min/60)*100 + min %% 60
}

然后,您可以根据需要汇总分钟数。我会亲自将它们放在 xts 对象中并使用apply.weekly

library(xts)
x <- xts(hour2min(godin$TIME), as.Date(godin$date2), dimnames=list(NULL,"MINS"))
w <- apply.weekly(x, mean)
w$TIME <- min2hour(w$MINS)
#                MINS     TIME
# 2004-07-18 580.0000  940.000
# 2004-08-01 585.0000  945.000
# 2004-09-12 711.2500 1151.250
# 2005-08-02 747.5000 1227.500
# 2005-09-11 746.6667 1226.667
# 2005-09-13 764.1667 1244.167

秒数仍然是 100 分之一分钟,但可以更改...

于 2012-07-17T18:03:18.570 回答
1

如果您想要每周所有观察时间的平均值并且想要日期很重要(即今天 19:00 和明天 19:00 平均到明天早上 07:00),那么您可以这样做

godin$datetime <- as.POSIXct(paste(godin$date2, godin$TIME), format="%Y-%m-%d %H%M")
aggregate(godin$datetime, list(format(godin$datetime, "%W/%g")), mean)

#  Group.1                   x
#1   28/04 2004-07-18 09:40:00
#2   30/04 2004-07-31 01:45:00
#3   31/05 2005-08-02 00:27:30
#4   36/04 2004-09-10 13:51:15
#5   36/05 2005-09-11 00:26:40
#6   37/05 2005-09-13 00:44:10

但是,我认为您想要平均时间,并且您不关心日期(除了确定它是哪一周)。在这种情况下,您可以使用任意日期作为锚点,并将所有时间视为在该日期发生的时间。

godin$stime <- as.POSIXct(paste("1970-01-01", godin$TIME), format='%Y-%m-%d %H%M')
aggregate(godin$stime, list(format(godin$datetime, "%W/%g")), mean)

#  Group.1                   x
#1   28/04 1970-01-01 09:40:00
#2   30/04 1970-01-01 09:45:00
#3   31/05 1970-01-01 12:27:30
#4   36/04 1970-01-01 11:51:15
#5   36/05 1970-01-01 12:26:40
#6   37/05 1970-01-01 12:44:10

编辑

上述输出与@JoshuaUlrich 提供的输出之间的区别在于他是按周排序的。如果我对它们进行排序,它就像 Joshua 的,但用秒而不是 100 分之一分钟。format(虽然,由于您选择的规范,以相同的方式对它们进行排序有点棘手。)

out <- aggregate(godin$stime, list(format(godin$datetime, "%W/%g")), mean)
out[order(as.numeric(paste0(substr(out[, 1], 4, 5), substr(out[, 1], 1, 2)))), ]
#  Group.1                   x
#1   28/04 1970-01-01 09:40:00
#2   30/04 1970-01-01 09:45:00
#4   36/04 1970-01-01 11:51:15
#3   31/05 1970-01-01 12:27:30
#5   36/05 1970-01-01 12:26:40
#6   37/05 1970-01-01 12:44:10

编辑 2

如果你只是想取回一个格式化的字符串,你可以format在里面aggregate%H%M

out <- aggregate(godin$stime, list(format(godin$datetime, "%W/%g")), function(TIME) format(mean(TIME), "%H%M"))
out[order(as.numeric(paste0(substr(out[, 1], 4, 5), substr(out[, 1], 1, 2)))), ]
#  Group.1    x
#1   28/04 0940
#2   30/04 0945
#4   36/04 1151
#3   31/05 1227
#5   36/05 1226
#6   37/05 1244
于 2012-07-17T18:02:56.903 回答