dplyr mutate函数,用于垂直计算列(当前、上一个、下一个)中的值
我一直在寻找一种不用运气就能实现我所需要的东西的方法。 不久前,我发现了dplyr包及其潜力。我在想这个包裹可以做我想做的,我只是不知道怎么做。这是我数据的一小部分,但应该代表我的问题dplyr mutate函数,用于垂直计算列(当前、上一个、下一个)中的值,r,dplyr,R,Dplyr,我一直在寻找一种不用运气就能实现我所需要的东西的方法。 不久前,我发现了dplyr包及其潜力。我在想这个包裹可以做我想做的,我只是不知道怎么做。这是我数据的一小部分,但应该代表我的问题 dummy<-structure(list(time = structure(1:20, .Label = c("2015-03-25 12:24:00", "2015-03-25 21:08:00", "2015-03-25 21:13:00", "2015-03-25 21:47:00
dummy<-structure(list(time = structure(1:20, .Label = c("2015-03-25 12:24:00",
"2015-03-25 21:08:00", "2015-03-25 21:13:00", "2015-03-25 21:47:00",
"2015-03-26 03:08:00", "2015-04-01 20:30:00", "2015-04-01 20:34:00",
"2015-04-01 20:42:00", "2015-04-01 20:45:00", "2015-09-29 18:26:00",
"2015-09-29 19:11:00", "2015-09-29 21:21:00", "2015-09-29 22:03:00",
"2015-09-29 22:38:00", "2015-09-30 00:48:00", "2015-09-30 01:38:00",
"2015-09-30 01:41:00", "2015-09-30 01:45:00", "2015-09-30 01:47:00",
"2015-09-30 01:49:00"), class = "factor"), ID = c(1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L), station = c(1L, 1L, 1L, 2L, 3,
4L, 4L, 4L, 4L, 5L, 5L, 6L,
6L, 5, 5, 5L, 7, 7, 7L,
7)), .Names = c("time", "ID", "station"), class = "data.frame", row.names = c(NA,
-20L))
这里有一个使用
difftime
和dplyr
mutate函数的选项。首先,我们使用groupu by
操作来确保比较在ID和Station的每个唯一组合内。difftime
可用于计算差分时间,为方便起见,此处将单位设置为hours
。lag
和lead
功能也来自dplyr
软件包,用于向后或向前移动所选列。结合difftime的矢量化操作,可以计算当前行与上一行/下一行之间的时间差。我们使用abs
来确保结果是绝对值。%group\u by(ID,station)%%>%
变异(new.value=as.integer(
abs(difftime(time,lag(time,default=Inf),units=“hours”)<1 |
abs(difftime(时间,提前期(时间,默认值=Inf),units=“hours”)<1))
来源:本地数据帧[20 x 4]
分组:ID,站点[7]
时间ID station new.value
(时间)(int)(dbl)(int)
1 2015-03-25 12:24:00 1 1 0
2 2015-03-25 21:08:00 1 1 1
3 2015-03-25 21:13:00 1 1 1
4 2015-03-25 21:47:00 1 2 0
5 2015-03-26 03:08:00 1 3 0
6 2015-04-01 20:30:00 1 4 1
7 2015-04-01 20:34:00 1 4 1
8 2015-04-01 20:42:00 1 4 1
9 2015-04-01 20:45:00 1 4 1
10 2015-09-29 18:26:00 2 5 1
11 2015-09-29 19:11:00 2 5 1
12 2015-09-29 21:21:00 2 6 1
13 2015-09-29 22:03:00 2 6 1
14 2015-09-29 22:38:00 2 5 0
15 2015-09-30 00:48:00 2 5 1
16 2015-09-30 01:38:00 2 5 1
17 2015-09-30 01:41:00 2 7 1
18 2015-09-30 01:45:00 2 7 1
19 2015-09-30 01:47:00 2 7 1
20 2015-09-30 01:49:00 2 7 1
Psidom的答案很好——这里有一个数据表方法
library(data.table)
setDT(dummy)
# you do NOT want a factor for your time variable
dummy[, time := as.POSIXct(time) ]
dummy[, `:=`(lag_diff = c(Inf, diff(as.numeric(time))),
lead_diff = c(diff(as.numeric(time)), Inf)),
by = .(ID, station) ]
dummy[, new.value := as.integer(lag_diff < 3600 | lead_diff < 3600) ]
dummy
库(data.table)
setDT(虚拟)
#您不希望为时间变量指定一个因子
虚拟对象[,时间:=as.POSIXct(时间)]
dummy[,`:=`(lag_diff=c(Inf,diff(as.numeric(time))),
导程_diff=c(diff(作为数值(时间)),Inf)),
by=(ID,车站)]
dummy[,new.value:=as.integer(滞后_diff<3600 |超前_diff<3600)]
笨蛋
另一种使用R基函数的解决方案(sapply
和difftime
):
n=nrow(虚拟)
虚拟$new.value=
as.numeric(sapply(1:n,函数(i))
(我认为您不需要dplyr,我认为您只需要几个diff
操作。请注意,“Class”POSIXct“表示自1970年初以来(UTC时区)的(有符号)秒数,作为一个数字向量。”因此,您希望查找小于3600秒的差异。不确定是否有dplyr
,但data.table具有滚动联接,似乎可以以最有效的方式解决您的问题。最近的一篇文章详细介绍了该功能:。要提供一小时滚动,只需使用60*60(因为POSIXct是秒数)。通过这种方式,您应该能够使用二进制合并来检测这些行。如果纯性能不是您的目标,那么shift(x)
或c(NA,x[-.N])
/c(x[-1L],NA)
应该足以创建要比较的列。这确实是我想要的。请您详细说明一下,谢谢。
library(dplyr)
dummy %>% group_by(ID, station) %>%
mutate(new.value = as.integer(
abs(difftime(time, lag(time, default = Inf), units = "hours")) < 1 |
abs(difftime(time, lead(time, default = Inf), units = "hours")) < 1))
Source: local data frame [20 x 4]
Groups: ID, station [7]
time ID station new.value
(time) (int) (dbl) (int)
1 2015-03-25 12:24:00 1 1 0
2 2015-03-25 21:08:00 1 1 1
3 2015-03-25 21:13:00 1 1 1
4 2015-03-25 21:47:00 1 2 0
5 2015-03-26 03:08:00 1 3 0
6 2015-04-01 20:30:00 1 4 1
7 2015-04-01 20:34:00 1 4 1
8 2015-04-01 20:42:00 1 4 1
9 2015-04-01 20:45:00 1 4 1
10 2015-09-29 18:26:00 2 5 1
11 2015-09-29 19:11:00 2 5 1
12 2015-09-29 21:21:00 2 6 1
13 2015-09-29 22:03:00 2 6 1
14 2015-09-29 22:38:00 2 5 0
15 2015-09-30 00:48:00 2 5 1
16 2015-09-30 01:38:00 2 5 1
17 2015-09-30 01:41:00 2 7 1
18 2015-09-30 01:45:00 2 7 1
19 2015-09-30 01:47:00 2 7 1
20 2015-09-30 01:49:00 2 7 1
library(data.table)
setDT(dummy)
# you do NOT want a factor for your time variable
dummy[, time := as.POSIXct(time) ]
dummy[, `:=`(lag_diff = c(Inf, diff(as.numeric(time))),
lead_diff = c(diff(as.numeric(time)), Inf)),
by = .(ID, station) ]
dummy[, new.value := as.integer(lag_diff < 3600 | lead_diff < 3600) ]
dummy
n=nrow(dummy)
dummy$new.value=
as.numeric(sapply(1:n, function(i)
(i<n && (dummy[i,"ID"]==dummy[i+1,"ID"] && dummy[i,"station"]==dummy[i+1,"station"])
&& abs(as.numeric(difftime(dummy[i,"time"], dummy[i+1,"time"]), "hours"))<=1)
||
(i>1 && (dummy[i,"ID"]==dummy[i-1,"ID"] && dummy[i,"station"]==dummy[i-1,"station"])
&& abs(as.numeric(difftime(dummy[i,"time"], dummy[i-1,"time"]), "hours"))<=1)
))
# > dummy
# time ID station new.value
# 1 2015-03-25 12:24:00 1 1 0
# 2 2015-03-25 21:08:00 1 1 1
# 3 2015-03-25 21:13:00 1 1 1
# 4 2015-03-25 21:47:00 1 2 0
# 5 2015-03-26 03:08:00 1 3 0
# 6 2015-04-01 20:30:00 1 4 1
# 7 2015-04-01 20:34:00 1 4 1
# 8 2015-04-01 20:42:00 1 4 1
# 9 2015-04-01 20:45:00 1 4 1
# 10 2015-09-29 18:26:00 2 5 1
# 11 2015-09-29 19:11:00 2 5 1
# 12 2015-09-29 21:21:00 2 6 1
# 13 2015-09-29 22:03:00 2 6 1
# 14 2015-09-29 22:38:00 2 5 0
# 15 2015-09-30 00:48:00 2 5 1
# 16 2015-09-30 01:38:00 2 5 1
# 17 2015-09-30 01:41:00 2 7 1
# 18 2015-09-30 01:45:00 2 7 1
# 19 2015-09-30 01:47:00 2 7 1
# 20 2015-09-30 01:49:00 2 7 1