indicator <- data.frame(Index=1:4,Ind_A=rep(0,4),Ind_B=rep(0,4));
values <- data.frame(Index=c(1,3,3,4),Indicators=c('Ind_A','Ind_A','Ind_B','Ind_A'));
indicator[cbind(match(values$Index,indicator$Index),match(values$Indicators,names(indicator)))] <- 1;
indicator;
## Index Ind_A Ind_B
## 1 1 1 0
## 2 2 0 0
## 3 3 1 1
## 4 4 1 0
The most significant change in your edit is that indicator$Index
now does not contain unique values (at least not on its own), so a simple match()
from values$Index
to indicator$Index
is insufficient. Instead, we actually must run an outer()
equality test on both Index
and Index2
to get a matrix of logicals representing which rows in indicator
each values
row matches on both keys. Assuming the two-column composite key is unique, we can then calculate the row index in indicator
from the linear (vector) index returned by which()
.
indicator[cbind((which(outer(values$Index,indicator$Index,`==`)&outer(values$Index2,indicator$Index2,`==`))-1)%/%nrow(values)+1,match(values$Indicators,names(indicator)))] <- 1;
indicator;
## Index Index2 Ind_A Ind_B
## 1 1 10 1 1
## 2 1 11 1 0
## 3 2 10 0 1
## 4 2 12 1 0
## 5 3 10 1 0
## 6 3 12 1 0
## 7 4 10 1 1
## 8 4 12 1 0
Here's another solution using merge()
:
indicator[cbind(merge(values,cbind(indicator,row=1:nrow(indicator)))$row,match(values$Indicators,names(indicator)))] <- 1;
indicator;
## Index Index2 Ind_A Ind_B
## 1 1 10 1 1
## 2 1 11 1 0
## 3 2 10 0 1
## 4 2 12 1 0
## 5 3 10 1 0
## 6 3 12 1 0
## 7 4 10 1 1
## 8 4 12 1 0
Performance
The first solution is more performant:
first <- function() indicator[cbind((which(outer(values$Index,indicator$Index,`==`)&outer(values$Index2,indicator$Index2,`==`))-1)%/%nrow(values)+1,match(values$Indicators,names(indicator)))] <<- 1;
second <- function() indicator[cbind(merge(values,cbind(indicator,row=1:nrow(indicator)))$row,match(values$Indicators,names(indicator)))] <<- 1;
N <- 10000;
system.time({ replicate(N,first()); });
## user system elapsed
## 2.032 0.000 2.041
system.time({ replicate(N,first()); });
## user system elapsed
## 2.047 0.000 2.038
system.time({ replicate(N,second()); });
## user system elapsed
## 12.578 0.000 12.592
system.time({ replicate(N,second()); });
## user system elapsed
## 12.64 0.00 12.66