一种指示每行多个指标变量的有效方法?

lap*_*nio 5 r indicator dataframe

给出"空"指标数据帧:

Index    Ind_A    Ind_B
  1        0        0
  2        0        0
  3        0        0
  4        0        0
Run Code Online (Sandbox Code Playgroud)

和值的数据框:

Index    Indicators
  1         Ind_A
  3         Ind_A
  3         Ind_B
  4         Ind_A
Run Code Online (Sandbox Code Playgroud)

我想最终得到:

Index    Ind_A    Ind_B
  1        1        0
  2        0        0
  3        1        1
  4        1        0
Run Code Online (Sandbox Code Playgroud)

没有for循环有没有办法做到这一点?

bgo*_*dst 1

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
Run Code Online (Sandbox Code Playgroud)

您的编辑中最重要的变化是indicator$Index现在包含唯一值(至少不包含唯一值),因此简单的match()fromvalues$Indexindicator$Index是不够的。相反,我们实际上必须对outer()两者运行相等性测试Index,并Index2获得一个逻辑矩阵,表示indicatorvalues行中的哪些行在两个键上匹配。假设两列复合键是唯一的,我们可以indicator根据 返回的线性(向量)索引计算行索引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
Run Code Online (Sandbox Code Playgroud)

这是另一个使用以下解决方案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
Run Code Online (Sandbox Code Playgroud)

表现

第一个解决方案性能更高:

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
Run Code Online (Sandbox Code Playgroud)