我正在尝试创建一个指示序列结束的向量。
我的数据看起来像这样:
id time var wake
1 1 1 sleep 0
2 1 2 sleep 0
3 1 3 sleep 0
4 1 4 0 0
5 1 5 0 0
我想要的是这个(输出想要)
id time var wake
1 1 1 sleep 0
2 1 2 sleep 0
3 1 3 sleep 0
4 1 4 0 1
5 1 5 0 0
6 1 6 0 0
7 1 7 0 0
8 1 8 sleep 0
9 1 9 sleep 0
10 1 10 sleep 0
11 2 1 sleep 0
12 2 2 sleep 0
13 2 3 sleep 0
14 2 4 sleep 0
15 2 5 sleep 0
16 2 6 0 1
17 2 7 0 0
18 2 8 0 0
19 2 9 sleep 0
20 2 10 sleep 0
我在考虑像
这样的东西library(dplyr)
dt$time = as.numeric(as.character(dt$time))
dt$var = ifelse(dt$var == 'sleep', 1, 0)
dt = dt %>% group_by(id) %>%
mutate(grp = cumsum(var != lag(var, default = var[1])))
dt$wake = 0
dt$wake [dt$grp == 1] <- 1
然而,它并没有发现第一集
数据
dt = structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("1",
"2"), class = "factor"), time = structure(c(1L, 3L, 4L, 5L, 6L,
7L, 8L, 9L, 10L, 2L, 1L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 2L), .Label = c("1",
"10", "2", "3", "4", "5", "6", "7", "8", "9"), class = "factor"),
var = structure(c(2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L), .Label = c("0",
"sleep"), class = "factor")), .Names = c("id", "time", "var"
), row.names = c(NA, -20L), class = "data.frame")
答案 0 :(得分:4)
使用库data.table
的一次传递:
setDT(dt)
dt[,wake:=( c(0,diff( rleid(var) ) == 1) & var != "sleep"),by=id]
我们的想法是获得var(rleid
)的运行长度编码:
> dt[,rleid(var),by=id][,V1]
[1] 1 1 1 2 2 2 2 3 3 3 1 1 1 1 1 2 2 2 3 3
从睡眠状态变为0时,它的差异+1,或者在睡眠状态下为0,在更换组时为负值(从1开始):
> diff(dt[,rleid(var),by=id][,V1])
[1] 0 0 1 0 0 0 1 0 0 -2 0 0 0 0 1 0 0 1 0
如果它为1且var不是睡眠,则获取一个TRUE值(如果将整个事物包装到as.numeric
中,则可以为1)。
输出:
nrow id time var wake
1: 1 1 1 sleep FALSE
2: 2 1 2 sleep FALSE
3: 3 1 3 sleep FALSE
4: 4 1 4 0 TRUE
5: 5 1 5 0 FALSE
6: 6 1 6 0 FALSE
7: 7 1 7 0 FALSE
8: 8 1 8 sleep FALSE
9: 9 1 9 sleep FALSE
10: 10 1 10 sleep FALSE
11: 11 2 1 sleep FALSE
12: 12 2 2 sleep FALSE
13: 13 2 3 sleep FALSE
14: 14 2 4 sleep FALSE
15: 15 2 5 sleep FALSE
16: 16 2 6 0 TRUE
17: 17 2 7 0 FALSE
18: 18 2 8 0 FALSE
19: 19 2 9 sleep FALSE
20: 20 2 10 sleep FALSE
答案 1 :(得分:3)
以下内容适用于dplyr
:
library(dplyr)
dt <- dt %>% group_by(id) %>%
mutate(wake = as.integer(var == '0' & var != lag(var, default = var[1])))
##Source: local data frame [20 x 4]
##Groups: id [2]
##
## id time var wake
## <fctr> <fctr> <fctr> <dbl>
##1 1 1 sleep 0
##2 1 2 sleep 0
##3 1 3 sleep 0
##4 1 4 0 1
##5 1 5 0 0
##6 1 6 0 0
##7 1 7 0 0
##8 1 8 sleep 0
##9 1 9 sleep 0
##10 1 10 sleep 0
##11 2 1 sleep 0
##12 2 2 sleep 0
##13 2 3 sleep 0
##14 2 4 sleep 0
##15 2 5 sleep 0
##16 2 6 0 1
##17 2 7 0 0
##18 2 8 0 0
##19 2 9 sleep 0
##20 2 10 sleep 0
将var
与lag
var
进行比较,因为OP会检测sleep
和0
之间的过渡(或剧集),但添加条件var
必须0
仅标记从sleep
到0
的{{1}}转换为wake
。
答案 2 :(得分:3)
假设您要标记每个id
的所有唤醒:
1)没有软件包请注意,如果x
和y
符合逻辑,则x - y > 0
iff x
为TRUE
且{ {1}}是y
。因此,我们有以下不使用包:
FALSE
2)dplyr 或者它可以用dplyr这样写:
transform(dt, wake = ave(var == 0, id, FUN = function(x) c(0, diff(x) > 0)))
3)动物园我们可以在每个library(dplyr)
dt %>% group_by(id) %>% mutate(wake = c(0, diff(var == 0) > 0)) %>% ungroup()
上使用rollapplyr
来查找序列
id
中的c(FALSE, TRUE)
。添加var==0
可确保结果为数字。
0
注意:如果您只想标记每个library(zoo)
roll <- function(x) rollapplyr(x, 2, identical, c(FALSE, TRUE), fill = 0)
transform(dt, wake = ave(var == 0, id, FUN = roll) + 0)
的第一个觉醒,如果id
是以上任何一个的结果,那么:
out
答案 3 :(得分:2)
这样做的一种丑陋方式可能是通过i:th +1来减去i:th值来查看睡眠是否结束,如下所示:
vec<-ifelse(dt$var=="sleep",1,0) #creating a vector for sleeping/not sleeping
tg<-c(0,vec[1:(length(vec)-1)])-vec #if values are == 1, i.e. first episode of not sleeping
然后您可以编写以下代码来获取wake
:
ifelse(tg==1,1,0) [1] 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
编辑:感谢下面的评论,我更新了我的答案。
vec<-ifelse(dt$var=="sleep",1,0)
lapply(unique(dt$id), function(x) ifelse(c(0,vec[min(which(dt$id==x)):(max(which(dt$id==x))-1)])-vec[dt$id==x]==1,1,0))
答案 4 :(得分:1)
不是很优雅,但这可以胜任。
确保事先按身份和时间对dt
进行排序。
dt$id <- as.character(dt$id)
dt$time <- as.integer(as.character(dt$time))
dt$var <- as.character(dt$var)
dt <- dplyr::arrange(dt, id, time)
dt$wake <- 0
dt$wake[which(dt$var == "0" & lag(dt$var) == "sleep" &
dt$id == lag(dt$id))] <- 1