R 按日期和小时划分数据; for 循环还是 sapply()?
R subset data by date and hour; for loop or sapply()?
假设的数据框表示一群羊的项圈上有 rfid 芯片。整个现场都有数据收集器,调制解调器连接在电线杆上。每当一只独特的绵羊进入这些杆之一的范围内时,它就被视为 'event',它存储在连接到杆上调制解调器的 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
?
在正确方向上的任何一点都会非常有帮助。
我认为您想要做的事情的一种方法是使用 format
从 checkin_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)
备注:
- 使用
mutate
从 checkin_time
. 中删除的日期和时间创建列 Date
和 Hour
group_by
Date
和 Hour
并使用 summarise
到 sum
每个 Date
的所有 number_events
和Hour
.
- 使用
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
假设的数据框表示一群羊的项圈上有 rfid 芯片。整个现场都有数据收集器,调制解调器连接在电线杆上。每当一只独特的绵羊进入这些杆之一的范围内时,它就被视为 'event',它存储在连接到杆上调制解调器的 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
?
在正确方向上的任何一点都会非常有帮助。
我认为您想要做的事情的一种方法是使用 format
从 checkin_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)
备注:
- 使用
mutate
从checkin_time
. 中删除的日期和时间创建列 group_by
Date
和Hour
并使用summarise
到sum
每个Date
的所有number_events
和Hour
.- 使用
tidyr
中的spread
创建表格结果,其中Date
为行,Hours
为列。
Date
和 Hour
我修改了您发布的输入数据 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