I want to create a conditional dummy variable. Assume that I have a dataset that looks something like this:
Subject Year X X1
A 1990 1 0
A
How about this?
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)
Here's another example using Base R. I'm not 100% I understand the exact details of the question, but this pattern should solve your problem.
ave
is great for broadcasting a summarized vector back to the original dimensions of the data. But if you look at the function body for ave
it is just using split
under the hood. We can do the same and create multiple columns per chunk instead of just one:
# 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)