sapply function(x) 其中 x 是子集参数
sapply function(x) where x is subsetted argument
所以,我想从两个现有向量(数字)中的信息生成一个新向量,一个设置参与者的 id,另一个指示观察编号。每个参与者都被观察了不同的时间。
现在,新向量应该声明:0 when obs_no=1; 1 当 obs_no=该 id 的最后一次观察; NA 介于两者之间。
id obs_no new_vector
1 1 0
1 2 NA
1 3 NA
1 4 NA
1 5 1
2 1 0
2 2 1
3 1 0
3 2 NA
3 3 1
我想我可以使用像这样的代码为每个 ID 单独执行此操作
new_vector <- c(0, rep(NA, times=length(obs_no[id==1])-2), 1)
或者我猜只是使用 max() 但它不会有任何区别。
但是手动添加每个参与者真的很不方便,因为我有很多案例。我不知道如何制作通用函数。我尝试使用 sapply 定义一个函数 (x) 但无法让它工作,因为 x 位于子集括号内。
任何建议都会有所帮助。谢谢。
使用split
:
result = lapply(split(obs_no, id), function (x) c(0, rep(NA, length(x) - 2), 1))
这为您提供了一个向量列表。您可以像这样将它们重新粘贴在一起:
do.call(c, result)
ave
救援:
dat$newvar <- NA
dat$newvar <- with(dat,
ave(newvar, id, FUN=function(x) replace(x, c(length(x),1), c(1,0)) )
)
或者使用一点duplicated()
乐趣:
dat$newvar <- NA
dat$newvar[!duplicated(dat$id, fromLast=TRUE)] <- 1
dat$newvar[!duplicated(dat$id)] <- 0
双方都给予:
# id obs_no new_vector newvar
#1 1 1 0 0
#2 1 2 NA NA
#3 1 3 NA NA
#4 1 4 NA NA
#5 1 5 1 1
#6 2 1 0 0
#7 2 2 1 1
#8 3 1 0 0
#9 3 2 NA NA
#10 3 3 1 1
您也可以使用 dplyr
str <- "
id obs_no new_vector
1 1 0
1 2 NA
1 3 NA
1 4 NA
1 5 1
2 1 0
2 2 1
3 1 0
3 2 NA
3 3 1
"
dt <- read.table(textConnection(str), header = T)
library(dplyr)
dt %>% group_by(id) %>%
mutate(newvar = if_else(obs_no==1,0L,if_else(obs_no==max(obs_no),1L,as.integer(NA))))
我们可以使用data.table
library(data.table)
i1 <- setDT(df1)[, .I[seq_len(.N) %in% c(1, .N)], id]$V1
df1[i1, newvar := c(0, 1)]
df1
# id obs_no new_vector newvar
# 1: 1 1 0 0
# 2: 1 2 NA NA
# 3: 1 3 NA NA
# 4: 1 4 NA NA
# 5: 1 5 1 1
# 6: 2 1 0 0
# 7: 2 2 1 1
# 8: 3 1 0 0
# 9: 3 2 NA NA
#10: 3 3 1 1
所以,我想从两个现有向量(数字)中的信息生成一个新向量,一个设置参与者的 id,另一个指示观察编号。每个参与者都被观察了不同的时间。
现在,新向量应该声明:0 when obs_no=1; 1 当 obs_no=该 id 的最后一次观察; NA 介于两者之间。
id obs_no new_vector
1 1 0
1 2 NA
1 3 NA
1 4 NA
1 5 1
2 1 0
2 2 1
3 1 0
3 2 NA
3 3 1
我想我可以使用像这样的代码为每个 ID 单独执行此操作
new_vector <- c(0, rep(NA, times=length(obs_no[id==1])-2), 1)
或者我猜只是使用 max() 但它不会有任何区别。
但是手动添加每个参与者真的很不方便,因为我有很多案例。我不知道如何制作通用函数。我尝试使用 sapply 定义一个函数 (x) 但无法让它工作,因为 x 位于子集括号内。
任何建议都会有所帮助。谢谢。
使用split
:
result = lapply(split(obs_no, id), function (x) c(0, rep(NA, length(x) - 2), 1))
这为您提供了一个向量列表。您可以像这样将它们重新粘贴在一起:
do.call(c, result)
ave
救援:
dat$newvar <- NA
dat$newvar <- with(dat,
ave(newvar, id, FUN=function(x) replace(x, c(length(x),1), c(1,0)) )
)
或者使用一点duplicated()
乐趣:
dat$newvar <- NA
dat$newvar[!duplicated(dat$id, fromLast=TRUE)] <- 1
dat$newvar[!duplicated(dat$id)] <- 0
双方都给予:
# id obs_no new_vector newvar
#1 1 1 0 0
#2 1 2 NA NA
#3 1 3 NA NA
#4 1 4 NA NA
#5 1 5 1 1
#6 2 1 0 0
#7 2 2 1 1
#8 3 1 0 0
#9 3 2 NA NA
#10 3 3 1 1
您也可以使用 dplyr
str <- "
id obs_no new_vector
1 1 0
1 2 NA
1 3 NA
1 4 NA
1 5 1
2 1 0
2 2 1
3 1 0
3 2 NA
3 3 1
"
dt <- read.table(textConnection(str), header = T)
library(dplyr)
dt %>% group_by(id) %>%
mutate(newvar = if_else(obs_no==1,0L,if_else(obs_no==max(obs_no),1L,as.integer(NA))))
我们可以使用data.table
library(data.table)
i1 <- setDT(df1)[, .I[seq_len(.N) %in% c(1, .N)], id]$V1
df1[i1, newvar := c(0, 1)]
df1
# id obs_no new_vector newvar
# 1: 1 1 0 0
# 2: 1 2 NA NA
# 3: 1 3 NA NA
# 4: 1 4 NA NA
# 5: 1 5 1 1
# 6: 2 1 0 0
# 7: 2 2 1 1
# 8: 3 1 0 0
# 9: 3 2 NA NA
#10: 3 3 1 1