我想创建一个条件虚拟变量。假设我有一个看起来像这样的数据集:
Subject Year X X1
A 1990 1 0
A 1991 1 0
A 1992 2 0
A 1993 3 0
A 1994 4 0
A 1995 4 1
B 1990 0 0
B 1991 1 0
B 1992 1 0
B 1993 2 0
B 1994 3 0
C 1990 1 0
C 1991 2 0
C 1992 3 1
C 1993 3 0
D 1990 1 0
D 1991 2 0
D 1992 3 0
D 1993 4 1
D 1994 5 0
E 1990 1 0
E 1991 1 0
E 1992 2 1
E 1993 3 0
让我们调用这个条件变量: Q1to3_noX1 。另一个感兴趣的变量是 Q1to3 。
Q1to3 变量也是一个虚拟变量,当X达到值3时指示1,否则为0(对于每个主题)。如果X为4或更大,则 Q1to3 变量应为0.X是累积变量(0,1,2,3,4 ......)。换句话说,如果最大X值为3, Q1to3 为1。
我使用:data$Q1to3 <- ave(data$X, data$Subject, FUN = function(x) if (max(x) == 3) 1 else 0)
创建了这个变量(感谢@ Zelazny7)。
Q1to3_noX1 变量与 Q1to3 变量非常相似,但与 Q1to3 相反,它以X1变量为条件。更确切地说,如果在接下来的5年中X1 = 1(从 Q1to3 的第一年开始计算), Q1to3_no5 应为0.换句话说,如果a)最大X值为3,则 Q1to3_noX1 应为1; b)如果5年后X1 = 0(否则为0)。
我从question了解到我应该使用rle
函数。但是,我无法在这种特殊情况下应用它。你有什么建议吗?
理想的结果应如下所示:
Subject Year X X1 Q1to3 Q1to3_noX1
A 1990 1 0 0 0
A 1991 1 0 0 0
A 1992 2 0 0 0
A 1993 3 0 0 0
A 1994 4 0 0 0
A 1995 4 1 0 0
B 1990 0 0 1 0
B 1991 1 0 1 1
B 1992 1 0 1 1
B 1993 2 0 1 1
B 1994 3 0 1 1
C 1990 1 0 1 0
C 1991 2 0 1 0
C 1992 3 1 1 0
C 1993 3 0 1 0
D 1990 1 0 0 0
D 1991 2 0 0 0
D 1992 3 0 0 0
D 1993 4 1 0 0
D 1994 5 0 0 0
E 1990 1 0 1 0
E 1991 1 0 1 0
E 1992 2 1 1 0
E 1993 3 0 1 0
可重复的样本:
> dput(data)
structure(list(Subject = structure(c(1L, 1L, 1L, 1L, 1L, 1L,
2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 5L, 5L,
5L, 5L), .Label = c("A", "B", "C", "D", "E"), class = "factor"),
Year = c(1990L, 1991L, 1992L, 1993L, 1994L, 1995L, 1990L,
1991L, 1992L, 1993L, 1994L, 1990L, 1991L, 1992L, 1993L, 1990L,
1991L, 1992L, 1993L, 1994L, 1990L, 1991L, 1992L, 1993L),
X = c(1L, 1L, 2L, 3L, 4L, 4L, 0L, 1L, 1L, 2L, 3L, 1L, 2L,
3L, 3L, 1L, 2L, 3L, 4L, 5L, 1L, 1L, 2L, 3L), X1 = c(0L, 0L,
0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L,
0L, 1L, 0L, 0L, 0L, 1L, 0L), Q1to3 = c(0L, 0L, 0L, 0L, 0L,
0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L,
1L, 1L, 1L, 1L), Q1to3_noX1 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L,
1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L)), .Names = c("Subject", "Year", "X", "X1", "Q1to3",
"Q1to3_noX1"), class = "data.frame", row.names = c(NA, -24L))
答案 0 :(得分:1)
这个怎么样?
data$cX1 <- do.call("c",tapply(data$X1, data$Subject, FUN = function(x){
nx=length(x) #i=1
sx=c()
if (nx<5) sx[1:nx]<-sum(x[1:nx]) else
for(i in 1:nx)sx[i]<-sum(x[i:min(i+5-1,nx)])
sx
},simplify = T))
data$Q1to3_noX1f2<-ifelse(data$Q1to3==1 & data$cX1==0,1,0)
答案 1 :(得分:1)
这是使用Base R的另一个例子。我不是100%我理解问题的确切细节,但这种模式应该可以解决你的问题。
ave
非常适合将汇总向量广播回数据的原始维度。但是如果你看一下ave
的函数体,它只是在引擎盖下使用split
。我们可以做同样的事情并为每个块创建多个列而不只是一个:
# split the data.frame
s <- split(df, df$Subject)
## calculate both columns at once per subject
both <- lapply(s, function(chunk) {
Q1to3 <- if (max(chunk$X) == 3) 1 else 0
Q1to3_noX1 <- if (Q1to3 == 1 & all(chunk$X1 == 0)) 1 else 0
data.frame(Q1to3, Q1to3_noX1)
})
## cbind them back together and unsplit
out <- unsplit(Map(cbind, s, both), df$Subject)