【问题标题】:R subset data by date and hour; for loop or sapply()?R 按日期和小时划分数据子集; for 循环还是 sapply()?
【发布时间】:2017-02-16 22:06:56
【问题描述】:

假设的数据框表示一群羊的项圈上带有 rfid 芯片。在整个现场都有连接到电线杆的数据收集器。每次独特的绵羊进入其中一个杆的范围内时,它都算作一个“事件”,它存储在连接到杆上调制解调器的 arduino 设备中。每个 arduino 设备都有一个地址,大约每五分钟,它就会通过调制解调器调用一次以报告其状态和事件数量。

> head(wow)
  address        checkin_time status_id number_events
1      11 2016-08-08 00:04:40         7            10
2      11 2016-08-08 00:09:53         7            13
3      11 2016-08-08 00:15:06         7            12
4      11 2016-08-08 00:20:20         7            11
5      11 2016-08-08 00:25:33         7            13
6      11 2016-08-08 00:30:45         7             5

我正在尝试创建一个新矩阵,其中包含所有唯一日期作为行,一天内的每个唯一小时作为列,并且它们汇总了该日期时间的事件总数。

这是我的(截断的)代码:

allDays <- unique(as.Date(wow$checkin_time))
for (d in allDays) {
oneAM <- subset(wow, as.POSIXct(wow$checkin_time) >= as.POSIXct(paste(d,'00:00:00')) & as.POSIXct(wow$checkin_time) <= as.POSIXct(paste(d, '00:59:59')))
twoAM <- subset(wow, as.POSIXct(wow$checkin_time) >= as.POSIXct(paste(d,'01:00:00')) & as.POSIXct(wow$checkin_time) <= as.POSIXct(paste(d, '01:59:59')))
threeAM <- subset(wow, as.POSIXct(wow$checkin_time) >= as.POSIXct(paste(d,'02:00:00')) & as.POSIXct(wow$checkin_time) <= as.POSIXct(paste(d, '02:59:59')))
enter code here
. . .

elevenPM <- subset(wow, as.POSIXct(wow$checkin_time) >= as.POSIXct(paste(d,'22:00:00')) & as.POSIXct(wow$checkin_time) <= as.POSIXct(paste(d, '22:59:59')))
twelvePM <- subset(wow, as.POSIXct(wow$checkin_time) >= as.POSIXct(paste(d,'23:00:00')) & as.POSIXct(wow$checkin_time) <= as.POSIXct(paste(d, '23:59:59')))
dayAsHours <- c(sum(oneAM$number_events), sum(twoAM$number_events), sum(threeAM$number_events), sum(fourAM$number_events), sum(fiveAM$number_events), sum(sixAM$number_events), 
                sum(sevenAM$number_events), sum(eightAM$number_events), sum(nineAM$number_events), sum(tenAM$number_events), sum(elevenAM$number_events), 
                sum(twelveAM$number_events), sum(onePM$number_events), sum(twoPM$number_events), sum(threePM$number_events), sum(fourPM$number_events), 
                sum(fivePM$number_events), sum(sixPM$number_events), sum(sevenPM$number_events), sum(eightPM$number_events), sum(ninePM$number_events), 
                sum(tenPM$number_events), sum(elevenPM$number_events), sum(twelvePM$number_events))
dateMatrix <- rbind(dateMatrix, dayAsHours)
}

上面的代码在硬编码时适用于单个值d,但当我将它包围在 for 循环中时它就停止了。

我得到的错误是:

Error in as.POSIXlt.character(x, tz, ...) : 
character string is not in a standard unambiguous format

另外,我知道我应该在这里使用sapply() 而不是for-loop,但是我很难弄清楚如何构建该函数。 wow 是函数将应用到的数据资产,还是 allDays

任何正确方向的点都会非常有帮助。

【问题讨论】:

  • cut 将适用于 POSIXt 数据,因此您可以创建两个变量,一个只有一个日期,另一个是按小时切割的日期时间并使用 data.tabledplyr 与这两个聚合,然后重塑将按小时切割的变量移动到列。

标签: r for-loop subset sapply


【解决方案1】:

我认为您想要做的一种方法是使用formatcheckin_time 中删除日期和时间。然后使用dplyr:

library(dplyr)
library(tidyr)
result <- wow %>% mutate(Date=format(checkin_time, format="%Y-%m-%d"),
                         Hour=format(checkin_time, format="%H")) %>%
                  group_by(Date,Hour) %>% 
                  summarise(number_events=sum(number_events)) %>%
                  spread(Hour, number_events)

注意事项:

  1. 使用mutatecheckin_time 中剥离的日期和小时创建列DateHour
  2. group_by DateHour 并使用 summarisesum 将所有 number_events 用于每个 DateHour
  3. 使用tidyr 中的spread 创建表格结果,其中Date 作为行,Hours 作为列。

我修改了您发布的输入数据wow 以添加更多日期和时间:

wow <- structure(list(address = c(11L, 11L, 11L, 11L, 11L, 11L), checkin_time = structure(c(1470629080, 
1470629393, 1470716106, 1470720020, 1470803133, 1470803445), class = c("POSIXct", 
"POSIXt"), tzone = ""), status_id = c(7L, 7L, 7L, 7L, 7L, 7L), 
    number_events = c(10L, 13L, 12L, 11L, 13L, 5L)), .Names = c("address", 
"checkin_time", "status_id", "number_events"), row.names = c(NA, 
-6L), class = "data.frame")
##  address        checkin_time status_id number_events
##1      11 2016-08-08 00:04:40         7            10
##2      11 2016-08-08 00:09:53         7            13
##3      11 2016-08-09 00:15:06         7            12
##4      11 2016-08-09 01:20:20         7            11
##5      11 2016-08-10 00:25:33         7            13
##6      11 2016-08-10 00:30:45         7             5

使用这些数据:

print(result)
##Source: local data frame [3 x 3]
##Groups: Date [3]
##
##        Date    00    01
##*      <chr> <int> <int>
##1 2016-08-08    23    NA
##2 2016-08-09    12    11
##3 2016-08-10    18    NA

【讨论】:

  • 谢谢,这太棒了。我以前没有研究过 dlplyr,但我认为我需要尽快学习该库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 2023-03-08
  • 2017-12-26
  • 1970-01-01
相关资源
最近更新 更多