【问题标题】:comparing elements of two tables, averaging existing elements and leaving NA for non-existing in R比较两个表的元素,平均现有元素并将 NA 保留为 R 中不存在的元素
【发布时间】:2014-10-21 09:31:58
【问题描述】:

我有两个表,第一个表 (T1) 表示数字范围,第二个表 (T2) 包括坐标和分数,这是 T1 第一列的细分。

我想计算 T2 的 score 的平均值,并插入到 T1 的范围内,如果相应的坐标不可用,则放入 NA。让我们说:

表 1:(T1)

    start    end    
    1000    1100
    1300    1390
    1530    1610
    1800    1905

表 2:(T2)

coordinate  score
1002         3
1004         1
1020         5
1087         4
1550         1
1559         7
1609         3
1805        2.5

结果:对T1范围内T2的元素求平均:例如:1000 to 1100 (3+1+5+1)/41300 to 1390之间没有得分,放置NA值等等。

start    end  mean-score  
1000    1100   3.25
1300    1390   NA
1530    1610   3.66
1800    1905   2.5

你能帮我在 R 中实现它吗?

谢谢。

【问题讨论】:

    标签: r compare average


    【解决方案1】:

    在@akrun 的提示下,我在“data.table”中遇到了foverlaps 函数。如果这是最好的方法,我不肯定(但它有效:-))

    library(data.table)
    T1 <- as.data.table(T1)
    T2 <- as.data.table(T2)
    setkey(T1, start, end)
    T2[, c("start", "end") := coordinate]
    foverlaps(T2, T1)[, list(score = mean(score)), by = list(start, end)]
    #    start  end    score
    # 1:  1000 1100 3.250000
    # 2:  1530 1610 3.666667
    # 3:  1800 1905 2.500000
    

    更新:

    正如@Arun在cmets中提到的,如果你在T2上也设置了Key,并且改变了foverlaps的顺序,你也可以得到NA

    setkey(T2, start, end)
    foverlaps(T1, T2)[, list(mean = mean(score)), by = list(i.start, i.end)]
    #    i.start i.end     mean
    # 1:    1000  1100 3.250000
    # 2:    1300  1390       NA
    # 3:    1530  1610 3.666667
    # 4:    1800  1905 2.500000
    

    【讨论】:

      【解决方案2】:

      一种方法是

      T1$mean_score <- sapply(seq_len(nrow(T1)), function(i) {x1 <- T1[i,]
                        mean(T2$score[T2$coordinate>x1[,1]& T2$coordinate<=x1[,2]])})
      
       T1
       #  start  end mean_score
      #1  1000 1100   3.250000
      #2  1300 1390        NaN
      #3  1530 1610   3.666667
      #4  1800 1905   2.500000
      

      数据

      T1 <- structure(list(start = c(1000L, 1300L, 1530L, 1800L), end = c(1100L, 
       1390L, 1610L, 1905L)), .Names = c("start", "end"), class = "data.frame", row.names = c(NA, 
       -4L))
      
      
      T2 <-  structure(list(coordinate = c(1002L, 1004L, 1020L, 1087L, 1550L, 
       1559L, 1609L, 1805L), score = c(3, 1, 5, 4, 1, 7, 3, 2.5)), .Names = c("coordinate", 
       "score"), class = "data.frame", row.names = c(NA, -8L))
      

      【讨论】:

      • between() from "data.table" 可能会使您的代码略短。 +1
      • @Ananda Mahto 谢谢,我正在寻找另一个我现在不记得的功能。
      • @Ananda Mahto 不,它是 data.table 中的新内容,但我不记得了。
      • 它以f 开头,但无论如何,我不确定它是否也有效。但是,谢谢。
      • @Ananda Mahto 你可以用between发帖。
      【解决方案3】:

      使用dplyr 函数rowwisedobetween 的可能性。

      library(dplyr)
      
      T1 %>%
        rowwise() %>%
        do(data.frame(., mean_score = mean(T2$score[between(T2$coordinate, left = .$start, right = .$end)])))
      #   start  end mean_score
      # 1  1000 1100   3.250000
      # 2  1300 1390        NaN
      # 3  1530 1610   3.666667
      # 4  1800 1905   2.500000
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-04
        • 2019-12-07
        相关资源
        最近更新 更多