根据大多数非零数据按日子集数据帧

时间:2013-02-06 17:57:39

标签: r

我有一个示例数据框:

a <- c(1:6)
b <- c("05/12/2012 05:00","05/12/2012 06:00","06/12/2012 05:00",
   "06/12/2012 06:00", "07/12/2012 09:00","07/12/2012 07:00")
c <-c("0","0","0","1","1","1")
df1 <- data.frame(a,b,c,stringsAsFactors = FALSE)

首先,我想确保R识别日期和时间格式,所以我使用了:

df1$b <- strptime(df1$b, "%d/%m/%Y %H:%M")

然而,这不可能是正确的,因为一旦我尝试查看新的数据帧,R总是会中止我的会话。

假设这个问题得到了解决,我希望根据数据框中包含“C”中不是零的最多数据的那一天得到数据的子集。在上面的例子中,我应该在2012年12月7日留下两个数据点。

我还有一个额外的相关问题 如果我想在一天中的特定时间段之间(比如在07:00到08:00之间)留下具有最​​多非零值的数据子集,我将如何进行此操作?

对于上述问题的任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

同意杰克。听起来像是R的损坏安装。首先要尝试的是删除保存先前会话结果的.Rdata文件。它们隐藏在Mac和Windows中,因此除非您“显示”'dotfiles'(系统文件),否则操作系统文件管理器(Finder.app和Windows资源管理器)将不会显示它们。如何查找和删除该文件是特定于操作系统的任务。它将在你的工作目录中,你需要在R之外进行删除,因为一旦R启动它将锁定对它的访问。也有可能获得一个损坏的.history文件,但根据我的经验,这通常不是问题的根源。

如果不成功,您可能需要重新安装R。

答案 1 :(得分:2)

好吧,好消息是我有一个答案,坏消息是你有更多的问题要问自己。首先是坏消息:您需要考虑如何处理“c”具有相同数量的非零值的多天。我不会在这个答案中解决这个问题。

现在好消息:这很简单。

第1步:首先,让我们重新格式化您的数据框。由于我们正在改变几个变量(b到datetime和c到numeric)的数据类型,我们需要创建一个新数据框或重新校准旧数据框。我更喜欢保留原文并创建一个新原文,如下所示:

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

请注意,我还添加了'hour'和'date'变量。这是为了使我们的数据可以通过以后的聚合函数的那些字段轻松排序。

第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'函数允许我们在添加其他列时保留所有数据。在这种情况下,我们希望.(date)中每天的总和为'c'。按小时对数据进行子集化将在数据参数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"))并将其添加到分钟数除以60 as.numeric(format(b, "%M")) / 60以将分钟数转换为小时数。此外,由于我们正在处理更多列,我已经切换了最后的子语句来命名我们想要的列,而不是引用数字。一旦我处理的是不连续的列,我发现使用名称更容易调试。