从布雷纳德 - 罗宾逊的相似性中排除0

时间:2017-03-26 13:25:33

标签: r similarity

我使用Daniel Weidele中的以下方法计算一组数据的Brainerd-Robinson相似度(下面的代码)。我的行表示地点,而我的列表示在每个地方找到的人的年龄。我使用相似性来衡量哪些地方的人口构成相似,然后我在网络分析中使用输出。

我的问题是我的很多地方在某些年龄段中都有'0'人,因此相似性指数显示了这些地方之间的紧密联系。我想运行模型的两次迭代,i)其中'0'被考虑,而ii)忽略'0',即所以我只返回在正数据上生成的索引。

我尝试了各种从分析中排除'0'的方法,到目前为止还没有任何工作。有什么建议吗?感谢。

# function to load the observations
load = function() {
  p <- read.csv("observations.csv")  
  rownames(p) <- p[,1]
  p <- p[,c(2:6)]
  return(p)
}

# function to compute the normalized Brainerd-Robinson similarity for observations x
BR <- function(x) 
{
  rd <- dim(x)[1]
  results <- matrix(0,rd,rd)
  for (s1 in 1:rd) {
    for (s2 in 1:rd) {
      results[s1,s2] <- 1 - (sum(abs(x[s1, ] / sum(x[s1,]) - x[s2, ] / sum(x[s2,]))))/2
    }
  }
  rownames(results) <- rownames(x)
  colnames(results) <- rownames(x)
  return(results)
}

# load observations, compute Brainerd-Robinson similarity and write results to file
write.csv(BR(load()), "br.csv")

1 个答案:

答案 0 :(得分:0)

为什么不直接询问作者? :)

当你看行

results[s1,s2] <- 1 - (sum(abs(x[s1, ] / sum(x[s1,]) - x[s2, ] / sum(x[s2,]))))/2

这主要是魔术发生的地方。让我概述一下这里发生了什么,只看一下分配操作的右侧<-

1 - (sum(abs(x[s1, ] / sum(x[s1,]) - x[s2, ] / sum(x[s2,]))))/2

我们打电话

  • 向量x[s1,] 站点1的观察 OOS1 ),
  • 数字(或标量)sum(x[s1,]),然后sum(OOS1) 网站1的总和 SOS1 ),
  • 和向量x[s1,] / sum(x[s1,]) 站点1的归一化观察 NOS1

然后我们可以将作业的右侧部分重写为:

1 - (sum(abs(OOS1 / SOS1 - OOS2 / SOS2)))/2

1 - (sum(abs(NOS1 - NOS2)))/2

重要的是,NOS1和NOS2仍然是包含每个类别观测值数量的向量,只是标准化为站点中的比例。

现在是您问题的关键部分:abs(NOS1 - NOS2)

NOS1 - NOS2

简单地从另一个中减去一个向量。这是您要进行修改的地方,以便不考虑0值:

differenceIgnoreZeroes <- function(u, v) 
{
  # input vectors u and v should have equal length for this to work
  result <- vector()
  for (i in 1:length(u)) {
    if(u[i] == 0 || v[i] == 0) next # SKIP IF EITHER VALUE IS 0
    result[i] <- u[i] - v[i]    
  }
  return(result)
}

定义此函数后,我们编写differenceIgnoreZeroes(NOS1, NOS2)而不是NOS1-NOS2

我们接下来继续采用绝对值:

abs(differenceIgnoreZeroes(NOS1, NOS2))

由于生成的矢量现在包含&#39; NA&#39;值,当对向量求和时,我们需要小心不要考虑这些NA s,否则整个总和也会变为NA。因此,将参数 na.rm 设置为T(rue):

sum(abs(differenceIgnoreZeroes(NOS1,NOS2)), na.rm = T)

因此,我们的右手总分配如下:

1 - (sum(abs(differenceIgnoreZeroes(OOS1 / SOS1, OOS2 / SOS2)), na.rm = T))/2

进一步扩展到

1 - (sum(abs(differenceIgnoreZeroes(x[s1, ] / sum(x[s1,]), 
x[s2, ] / sum(x[s2,]))), na.rm = T))/2

我希望这有帮助!

干杯,

Daniel Weidele