【问题标题】:R - preserve order when using matching operators (%in%)R - 使用匹配运算符时保留顺序 (%in%)
【发布时间】:2012-05-22 03:12:13
【问题描述】:

我正在使用匹配运算符从单独的数据框中获取出现在矩阵中的值。但是,结果矩阵的值按照它们在数据框中出现的顺序排列,而不是在原始矩阵中。有没有办法使用匹配算子来保持原矩阵的顺序?

这是一个简单的例子:

vec=c("b","a","c"); vec

df=data.frame(row.names=letters[1:5],values=1:5); df

df[rownames(df) %in% vec,1]

这会产生> [1] 1 2 3,这是"a" "b" "c" 出现在数据框中的顺序。但是,我想生成>[1] 2 1 3,这是它们在原始向量中出现的顺序。

谢谢!

【问题讨论】:

    标签: r operators


    【解决方案1】:

    由于行名索引也适用于向量,我们可以更进一步并定义:

    '%ino%' <- function(x, table) {
        xSeq <- seq(along = x)
        names(xSeq) <- x
        Out <- xSeq[as.character(table)]
        Out[!is.na(Out)]
    }
    

    我们现在得到了想要的结果:

    df[rownames(df) %ino% vec, 1]
    [1] 2 1 3
    

    在函数内部,names() 会自动转换为字符,并使用 as.character() 更改表格,因此当 %ino% 的输入是数字时,这也可以正常工作:

    LETTERS[1:26 %in% 4:1]
    [1] "A" "B" "C" "D"
    
    
    LETTERS[1:26 %ino% 4:1]
    [1] "D" "C" "B" "A"
    

    在 %in% 之后,删除缺失值:

    LETTERS[1:26 %in% 3:-5]
    [1] "A" "B" "C"
    
    LETTERS[1:26 %ino% 3:-5]
    [1] "C" "B" "A"
    

    使用 %in% 时,逻辑序列沿被子集化对象的维度重复,而 %ino% 则不是这样:

    data.frame(letters, LETTERS)[1:5 %in% 3:-5,] 
    
        letters LETTERS
     1        a       A
     2        b       B
     3        c       C
     6        f       F
     7        g       G
     8        h       H
     11       k       K
     12       l       L
     13       m       M
     16       p       P
     17       q       Q
     18       r       R
     21       u       U
     22       v       V
     23       w       W
     26       z       Z
    
    
    data.frame(letters, LETTERS)[1:5 %ino% 3:-5,]
    
       letters LETTERS
     3       c       C
     2       b       B
     1       a       A
    

    【讨论】:

      【解决方案2】:

      使用match。

      df[match(vec, rownames(df)), ]
      # [1] 2 1 3
      

      请注意,如果您在 vec 或 rownames(df) 中有重复值,match 可能不会按预期运行。

      编辑: 我刚刚意识到行名索引会更简单、更优雅地解决您的问题:

      df[vec, ]
      # [1] 2 1 3
      

      【讨论】:

      • 使用行名索引的奖励积分,但两种解决方案都有效。谢谢!
      【解决方案3】:

      使用match(并为另一个向量中不匹配的元素去掉NA值):

      Filter(function(x) !is.na(x), match(rownames(df), vec))
      

      【讨论】:

      • 实际上,如果您使用 nomatch=0 进行匹配,对于不匹配的项目,匹配将返回 0 而不是 NA。由于 [] 的行选择只是忽略了 0,因此您可以将匹配结果目录粘贴到 [] 中,无需调用过滤器
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多