【问题标题】:compare multiple columns in one or two data frames r比较一个或两个数据帧 r 中的多列
【发布时间】:2020-01-31 04:41:56
【问题描述】:

我有一个数据框:

name<-c('a','b','c','d','e')
type<-c('x','x','y','x','y')
chr<- c('ch1','ch1','ch1','ch2','ch2')
pos<- c(5000, 5100, 4999,5500,5100)
df<-data.frame(name,type, chr,pos)


我想遍历每一行,如果类型不相等,并且 chr 相等,并且 pos 在 abs(100) 内,然后使用匹配项创建一个新的 df (使用匹配名称的新列)。 对于上述 df 行 1 和 3 将匹配,结果将是

理想情况下我不想要互惠匹配,所以我想要

如果更容易我可以根据类型分成两个dfs。

我尝试了合并和过滤器 (dplyr) 的变体,但无处可去。

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以根据type列拆分数据,做一个full_joinby'chr'列和filterpos列之间绝对值小于100的行。

    library(dplyr)
    
    df %>%
      group_split(type) %>%
      purrr::reduce(full_join, by = 'chr') %>%
      filter(abs(pos.x - pos.y) < 100)
    
    # A tibble: 1 x 7
    #  name.x type.x chr   pos.x name.y type.y pos.y
    #  <fct>  <fct>  <fct> <dbl> <fct>  <fct>  <dbl>
    #1  a      x      ch1    5000 c      y       4999
    

    然后您可以删除任何不需要的列并根据您的要求重命名它们。

    【讨论】:

      【解决方案2】:

      我相信这里的其他人会想出比行切片更优雅的东西,但如果你有一个包含所有匹配项的完整数据框,这似乎可行:

      library(tidyverse)
      
      find_matches <- function(i) {
        row_of_interest <- df[i, ]
        df_rest <- df[-i, ]
        names(df_rest) <- str_c(names(df_rest), ".x")
      
        df_rest %>% 
          cbind(row_of_interest) %>% 
          filter(type != type.x, abs(pos - pos.x) < 100) %>% 
          transmute(name, type, chr, pos, match = name.x)
      }
      
      map_dfr(1:5, find_matches)
      
        name type chr  pos match
      1    a    x ch1 5000     c
      2    b    x ch1 5100     e
      3    c    y ch1 4999     a
      4    e    y ch2 5100     b
      

      【讨论】:

        【解决方案3】:

        data.table 选项使用非等连接,对于大型数据集应该更快:

        library(data.table)
        setDT(df)[, c("s", "e") := .(pos - 100, pos + 100)]
        
        #perform non-equi join based on desired conditions
        pair <- df[df, on=.(chr, s<=pos, e>=pos), nomatch=0L,
            .(name=i.name[x.type!=i.type], match=x.name[x.type!=i.type])]
        
        #extract rows with matches while removing reciprocals
        df[unique(pair[, .(name=pmin(name, match), match=pmax(name, match))]), on=.(name)]
        

        输出:

           name type chr  pos    s    e match
        1:    a    x ch1 5000 4900 5100     c
        

        【讨论】:

          猜你喜欢
          • 2017-04-26
          • 1970-01-01
          • 2021-09-16
          • 1970-01-01
          • 2019-06-23
          • 2018-01-26
          • 1970-01-01
          • 2022-11-10
          相关资源
          最近更新 更多