如何计算R中列之间的特定差异

时间:2016-05-18 09:23:07

标签: r loops if-statement apply

我有一个数据框,我希望遍历每一列,并计算其行值与其他列的行值之间存在+1(不是-1!)差异的次数。例如,在第2列中,有4个行值大于它们的列1当量,第一个,第三个,第五个和第六个。

df <- read.table(header=T, text="
 v1  v2  v3  
  1   2   3   
  2   1   3  
  1   2   3   
  1   3   2   
  2   3   1   
  1   2   3  
 ")

看起来apply函数在这里很有用,但我对如何使用它有点困惑。

预期输出将类似于发生这种情况的计数矩阵。

   V1 V2 V3
V1 -  4  2
V2 4  -  3
V3 2  3  -

4 个答案:

答案 0 :(得分:2)

这也有效:

df <- read.table(header=T, text="
 v1  v2  v3  
 1   2   3   
 2   1   3  
 1   2   3   
 1   3   2   
 2   3   1   
 1   2   3")

ncols  <- ncol(df)
result <- matrix(nrow=ncols, ncol=ncols, 
                 dimnames = list(names(df),names(df)))

sapply(1:ncols, function(x) {
  result[(1:ncols)[-x],x] <<- colSums(df[,x]-df[,-x] == 1)
})

# Depending on whether you want a symmetric matrix or not:
result[lower.tri(result)] <- result[upper.tri(result)]

这会给你:

   v1 v2 v3
v1 NA  4  2
v2  4 NA  3
v3  2  3 NA

答案 1 :(得分:1)

sapply(colnames(df),function(v1){
      return(sapply(colnames(df),
                    function(v2){
                        return(sum(df[,v1]-df[,v2] == 1))
                    }))
  })

   v1 v2 v3
v1  0  4  2
v2  1  0  3
v3  1  1  0

如果您想要对称值,请改用abs(df[,v1]-df[,v2] == 1)中的sum

答案 2 :(得分:0)

作为列表的结果(没有硬编码名称,任何数量的列等):

library(data.table)

df <- read.table(header=T, text="
 v1  v2  v3  
                 1   2   3   
                 2   1   3  
                 1   2   3   
                 1   3   2   
                 2   3   1   
                 1   2   3  
                 ")

dt <- data.table(df)

col_comb <- combn(names(dt), 2, simplify = FALSE)
names(col_comb) <- sapply(col_comb, paste0, collapse = "-")

res <- invisible(lapply(col_comb, function(comb) {
  return(dt[, sum(get(comb[2]) - get(comb[1]) == 1)])
}))

结果:

$`v1-v2`
[1] 4

$`v1-v3`
[1] 2

$`v2-v3`
[1] 3

4列示例:

df <- read.table(header=T, text="
 v1  v2  v3  v4  
                 1   2   3   1
                 2   1   3   2
                 1   2   3   3
                 1   3   2   1
                 2   3   1   1
                 1   2   3   1
                 ")

# rest of code here

结果:

$`v1-v2`
[1] 4

$`v1-v3`
[1] 2

$`v1-v4`
[1] 0

$`v2-v3`
[1] 3

$`v2-v4`
[1] 2

$`v3-v4`
[1] 0

答案 3 :(得分:0)

您可以执行以下操作。我们的想法是通过列循环(使用sapply)并计算差异并输出精确值为1的差异数。相同的列比较产生NA

# function
foo <- function(i,y){
  a <- c(1:3) # number of data.frame columns
  a1 <- sapply(a, function(j,ii) if(a[j] == a[ii]) NA else sum((y[,ii] - y[,j]) == 1) ,i)
  a2 <- sapply(a, function(j,ii) if(a[j] == a[ii]) NA else sum((y[,j]  - y[,ii]) == 1) ,i)
  a1+a2-1
    }

sapply(1:ncol(df), foo, df)  
      [,1] [,2] [,3]
[1,]   NA    4    2
[2,]    4   NA    3
[3,]    2    3   NA