给出“空”指标数据框:
Index Ind_A Ind_B
1 0 0
2 0 0
3 0 0
4 0 0
和值的数据框:
Index Indicators
1 Ind_A
3 Ind_A
3 Ind_B
4 Ind_A
我想最终:
Index Ind_A Ind_B
1 1 0
2 0 0
3 1 1
4 1 0
如果没有for循环,有没有办法做到这一点?
答案 0 :(得分: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
您的修改中最重要的变化是indicator$Index
现在不包含唯一值(至少不是它自己的),所以来自{{match()
的简单values$Index
1}}到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
以下是使用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
<强>性能强>
第一种解决方案更具性能:
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
答案 1 :(得分:1)
我使用矩阵:
ind_mat <- as.matrix(ind_df[,-1]); rownames(ind_mat) <- ind_df[,1]
val_mat <- cbind(match(val_df$Index,ind_df[,1]),match(val_df$Indicators,names(ind_df[-1])))
ind_mat[val_mat] <- 1L
# Ind_A Ind_B
# 1 1 0
# 2 0 0
# 3 1 1
# 4 1 0
你可能不需要&#34;索引&#34;作为列,可以将它们放在rownames
。如果(i)您的值矩阵相对于索引矩阵较小且(ii)您的索引列等于1:nrow(ind_df)
,则应考虑存储在稀疏矩阵中。
关于对矩阵的强制,它只需要很少的时间,并且可以避免以后因任何矩阵运算而不得不强迫的麻烦。这是一个例子:
n = 1e4
nind = 1e3
y <- rnorm(n)
x <- matrix(sample(0:1,size=n*nind,replace=TRUE),ncol=nind)
xd <- data.frame(1:nrow(x),x)
# timing: 0.04 seconds on my computer
system.time(as.matrix(xd[,-1]))
# messiness, e.g., for OLS y~0+x: immense
solve(t(as.matrix(xd[,-1]))%*%as.matrix(xd[,-1]))%*%(t(as.matrix(xd[,-1]))%*%y)
最后一行可以避免保持matrix
左右;我不明白这一点。
答案 2 :(得分:1)
我会直接做:
df = transform(df, Index=factor(Index, level=min(Index):max(Index)))
as.data.frame.matrix(table(df))
# Ind_A Ind_B
#1 1 0
#2 0 0
#3 1 1
#4 1 0
数据:强>
df = structure(list(Index = c(1, 3, 3, 4), Indicators = c("Ind_A",
"Ind_A", "Ind_B", "Ind_A")), .Names = c("Index", "Indicators"
), row.names = c(NA, -4L), class = "data.frame")