我有以下数据
set.seed(11)
Data<-rbind(c(1:5),c(2:6))
Candidates <- matrix(1:25 + rnorm(25), ncol=5,
dimnames=list(NULL, paste0("x", 1:5)))
colnames(Data)<-colnames(Candidates)
我想从候选矩阵的每一行中减去我的数据的每一行 并返回最小的绝对差异 因此,对于第一行,我想找出可能的最小错误量
sum(abs(Data[1,]-Candidates[1,]))
sum(abs(Data[1,]-Candidates[2,]))
sum(abs(Data[1,]-Candidates[3,]))
sum(abs(Data[1,]-Candidates[4,]))
sum(abs(Data[1,]-Candidates[5,]))
在这种情况下,它是38.15826。目前我实际上并不想找出哪个候选行产生最小的绝对偏差,我只想知道每个数据行的最小绝对偏差。
我希望最终得到一个新的数据集,它具有我原始的数据和最小的偏差,例如:第一行是这样的:
x1 x2 x3 x4 x5 MinDev
1 2 3 4 5 38.15826
我真正的候选矩阵相对较小但我的真实数据非常大, 所以目前我正在构建一个循环
Err[i,]<- min(rbinds(
sum(abs(Data[i,]-Candidates[1,])),
sum(abs(Data[i,]-Candidates[2,]))...))
但我确信有一种更好,更自动化的方法,可以容纳大型数据矩阵和不同大小的候选矩阵。
有什么想法吗?
答案 0 :(得分:4)
您可以使用sweep
,rowSums
和apply
自动执行此操作
sum(abs(Data[1,]-Candidates[1,])) ## 38.15826
在Data
的第一行测试:
min(
rowSums(abs(
## subtract row 1 of Data from each row of Candidates
sweep(Candidates,2,Data[1,],"-"))))
## 38.15826
为了方便/可读性,将其封装在一个函数中:
getMinDev <- function(x) {
min(rowSums(abs(sweep(Candidates,2,x,"-"))))
}
现在适用于Data
的每一行:
cbind(Data,MinDev=apply(Data,1,getMinDev))
可能有一些方法比sweep
略快(例如@ e4e5f4答案中给出的矩阵计算),但这应该是一个很好的基线。我喜欢sweep
,因为它是描述性的,并不依赖于知道R使用列主矩阵排序。
答案 1 :(得分:4)
您可以使用apply
进行一些矩阵运算:
CalcMinDev <- function(x)
{
m <- t(matrix(rep(x, nrow(Candidates)), nrow=nrow(Candidates)))
min(rowSums(abs(m - Candidates)))
}
cbind(Data, MinDev=apply(Data, 1, CalcMinDev))
答案 2 :(得分:4)
根据@BenBolker建议将我的评论(使用dist
函数与method="manhattan"
)转换为答案:
想法:诀窍是如果你向dist
提供一个矩阵,它会将所有组合的距离作为下三角矩阵返回。
dist(rbind(Candidates, Data), method="manhattan")
# 1 2 3 4 5 6
# 2 8.786827
# 3 11.039044 3.718396
# 4 16.120267 7.333440 6.041076
# 5 21.465682 12.678855 10.426638 5.345415
# 6 38.158256 45.763021 48.015238 53.096461 58.441876
# 7 35.158256 40.763021 44.048344 48.096461 53.441876 5.000000
这里,第6行和第7行(从索引1到5)是你感兴趣的距离。所以,基本上,你只需要计算索引来提取你感兴趣的元素。
最终代码如下:
idx1 <- seq_len(nrow(Data)) + nrow(Candidates)
idx2 <- seq_len(ncol(Candidates))
tt <- dist(rbind(Candidates, Data), method="manhattan")
transform(Data, minDev = apply(as.matrix(tt)[idx1, idx2], 1, min))
# x1 x2 x3 x4 x5 minDev
# 6 1 2 3 4 5 38.15826
# 7 2 3 4 5 6 35.15826