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循环有没有办法做到这一点?
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$Index到indicator$Index是不够的。相反,我们实际上必须对outer()两者运行相等性测试Index,并Index2获得一个逻辑矩阵,表示indicator每values行中的哪些行在两个键上匹配。假设两列复合键是唯一的,我们可以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)