好吧,好消息是我有一个答案给你,坏消息是你有更多的问题要问自己。首先是坏消息:您需要考虑如何处理具有相同数量的“c”非零值的多天。我不会在这个答案中解决这个问题。
现在好消息:这真的很简单。
第 1 步:首先,让我们重新格式化您的数据框。由于我们要更改几个变量的数据类型(b 为日期时间,c 为数字),我们需要创建一个新的数据框或重新校准旧的数据框。我更喜欢保留原件并创建一个新的,如下所示:
a <- df1$a
b <- strptime(df1$b, "%d/%m/%Y %H:%M")
c <- as.numeric(df1$c)
hour <- as.numeric(format(b, "%H"))
date <- format(b, "%x")
df2 <- data.frame(a, b, c, hour, date)
# a b c hour date
# 1 1 2012-12-05 05:00:00 0 5 12/5/2012
# 2 2 2012-12-05 06:00:00 0 6 12/5/2012
# 3 3 2012-12-06 05:00:00 0 5 12/6/2012
# 4 4 2012-12-06 06:00:00 1 6 12/6/2012
# 5 5 2012-12-07 09:00:00 1 9 12/7/2012
# 6 6 2012-12-07 07:00:00 1 7 12/7/2012
请注意,我还添加了“小时”和“日期”变量。这是为了使我们的数据易于按这些字段排序,以供我们以后的聚合功能使用。
第 2 步:现在,让我们计算每天 06:00 到 08:00 之间有多少个非零值。由于我们使用的是“小时”值,这意味着“6”和“7”的值(代表 06:00 - 07:59)。
library(plyr)
df2 <- ddply(df2[df2$hour %in% 6:7,], .(date), mutate, non_zero=sum(c))
# a b c hour date non_zero
# 1 2 2012-12-05 06:00:00 0 6 12/5/2012 0
# 2 4 2012-12-06 06:00:00 1 6 12/6/2012 1
# 3 6 2012-12-07 07:00:00 1 7 12/7/2012 1
'plyr' 包非常适合这样的事情。“ddply”包专门将数据帧作为输入和输出(因此称为“dd”),而“mutate”函数允许我们在添加额外列的同时保留所有数据。在这种情况下,我们想要 'c' 中的每一天的总和.(date)
。在 data 参数中按小时对我们的数据进行子集处理df2[df2$hour %in% 6:7,]
,它表示向我们显示小时值在集合 {6,7} 中的行。
第 3 步:最后一步是按非零值的最大数量对数据进行子集化。我们可以删除我们使用的额外列并回到我们原来的三列。
subset_df <- df2[df2$non_zero==max(df2$non_zero),1:3]
# a b c
# 2 4 2012-12-06 06:00:00 1
# 3 6 2012-12-07 07:00:00 1
祝你好运!
更新:应 OP 的要求,我正在编写一个新的“ddply”函数,该函数还将包含一个用于绘图的时间列。
df2 <- ddply(df2[df2$hour %in% 6:7,], .(date), mutate, non_zero=sum(c), plot_time=as.numeric(format(b, "%H")) + as.numeric(format(b, "%M")) / 60)
subset_df <- df2[df2$non_zero==max(df2$non_zero),c("a","b","c","plot_time")]
我们需要将时间分解为一个连续变量,所以我选择了小时。以时间格式保留任何数据将需要我们稍后处理一些东西,并且使用字符串格式(如“hh:mm”)将限制您可以在其上使用的函数类型。连续数字是最灵活的,所以这里我们得到小时数as.numeric(format(b, "%H"))
并将其添加到分钟数除以 60as.numeric(format(b, "%M")) / 60
以将分钟转换为小时单位。另外,由于我们要处理更多的列,我已经切换了最后的子集语句来命名我们想要的列,而不是引用数字。一旦我处理了非连续顺序的列,我发现使用名称更容易调试。