【问题标题】:Find minimum deviation from vector from a matrix of possible vectors从可能的向量矩阵中找到向量的最小偏差
【发布时间】:2013-04-21 13:00:41
【问题描述】:

我有以下数据

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,]))...))

但我确信有更好、更自动化的方法来执行此操作,以便它可以容纳大型数据矩阵和不同大小的候选矩阵。

有什么想法吗?

【问题讨论】:

  • 在开头使用set.seed 使示例可重现。
  • 已编辑原始问题,我忘记定义种子。道歉

标签: r


【解决方案1】:

您可以使用 sweeprowSumsapply 自动执行此操作

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) sum(abs(vec1 - vec2)) 只是曼哈顿距离。 dist(rbind(vec1, vec2), method = "manhattan")
  • @Arun,为什么不作为答案发布? (如果您愿意,也可以编辑我的答案。)
  • @BenBolker,添加了答案。
  • 本,这很棒。谢谢
【解决方案2】:

您可以将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))

【讨论】:

  • 短一点:CalcMinDev &lt;- function(x)min(colSums(abs(t(Candidates) - x)))
  • +1,我试图避免创建矩阵,但我迷失在t() - colSums - rowSums
【解决方案3】:

按照@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

【讨论】:

  • 当然,您可以使用apply 为您需要的组合计算距离,而不是计算整个距离矩阵。
  • 真的很好,这很棒。实际上我之前也遇到过同样的事情,我使用sweep 解决了它,但这要好得多(我使用了eucl空间和曼哈顿)。
  • 有一个问题,是否有可能在对所有偏差求和之前以某种方式更多地权衡某些偏差?
  • @Dualinity,dist 函数调用C_Cdist(C 代码)。而且似乎没有选择。根据方法的不同,可能可以在计算距离之前乘以权重(未测试)。但我同意这样的选择会很方便。
猜你喜欢
  • 2023-03-14
  • 2021-08-05
  • 1970-01-01
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 1970-01-01
  • 2013-12-01
相关资源
最近更新 更多