【问题标题】:Two data frames, join ID's and position from one df if value is in the range of 2nd df两个数据框,如果值在第二个 df 的范围内,则从一个 df 连接 ID 和位置
【发布时间】:2019-10-09 05:26:56
【问题描述】:

从昨天开始,我一直在努力解决我的问题... 我认为,最好的解释是当我向您展示示例时,所以我有两个 df 的 x 和 y,它们看起来像这样:

ID_x <- c('x1','x2','x3','x4','x5','x6','x7','x8','x9','x10')
chr_x <- c('chr1','chr1','chr1','chr1','chr1','chr1','chr1','chr1','chrX','chrY')
start <- c(1,2,3,4,50,60,70,80,9,100)
stop <- c(10,20,30,40,500,600,700,800,95,1000)
x <- data.frame(ID_x,chr_x,start,stop)

> x
   ID_x chr_x start stop
1    x1  chr1     1   10
2    x2  chr1     2   20
3    x3  chr1     3   30
4    x4  chr1     4   40
5    x5  chr1    50  500
6    x6  chr1    60  600
7    x7  chr1    70  700
8    x8  chr1    80  800
9    x9  chrX     9   90
10  x10  chrY   100 1000

第二个:

ID_y <- c('y1','y2','y3','y4','y5','y6','y7','y8','y9','y10')
chr_y <- c('chr1','chr1','chr1','chr1','chr2','chr2','chr3','chr3','chrX','chrY')
pos_y <- c(8,9,15,31,41,2,81,8,91,8)
y <- data.frame(ID_y,chr_y,pos_y)

> y
   ID_y chr_y pos_y
1    y1  chr1     8
2    y2  chr1     9
3    y3  chr1    15
4    y4  chr1    31
5    y5  chr2    41
6    y6  chr2     2
7    y7  chr3    81
8    y8  chr3     8
9    y9  chrX    91
10  y10  chrY     8

现在我想根据范围(开始、停止)和 chr 将行从第二个 df (y) 映射到第一个 df (x)。 我想列出从 y df(如果它们满足条件)到 df x 的每一行的所有 id。 没有这样的 id_y,然后 NA。 所以预期的结果:

    ID_x chr_x start stop ID_y          pos_y
1    x1  chr1     1   10  y1,y2         8,9
2    x2  chr1     2   20  y1,y2,y3      8,9,15
3    x3  chr1     3   30  y1,y2,y3,y4   8,9,15,31
4    x4  chr1     4   40  y1,y2,y3,y4   8,9,15,31
5    x5  chr1    50  500  NA            NA
6    x6  chr1    60  600  NA            NA
7    x7  chr1    70  700  NA            NA
8    x8  chr1    80  800  NA            NA
9    x9  chrX     9   95  y9            91  
10  x10  chrY   100 1000  NA            NA

乍一看,我认为这是小菜一碟,但当我试图解决这个问题时......我尝试了几种方法...... 嵌套 apply()ifelse() 给了我一个巨大的矩阵,里面有很多 NA... 我发现了类似的问题和解决方案here,但我的原始数据集很大,df x 有 134748 行,df y 有 865859 行。我有内存分配错误,即使我试图用一个染色体来做这件事。

您能否给我一个提示如何做到这一点?

谢谢, 亚当

【问题讨论】:

标签: r dataframe dplyr apply


【解决方案1】:

使用data.table 连接应该有一个更有效的解决方案,但这是使用dplyr 的一种方法。我们首先通过"chr" 列对xy 执行left_join,然后在startstop 之间的filter 行,为每个chr_x、@ 创建一个逗号分隔的字符串987654331@ 和 stop 最后是 right_joinx 以使用 NA 获取缺失范围。

library(dplyr)

left_join(x, y, by = c("chr_x" = "chr_y")) %>%
   filter(data.table::between(pos_y, start, stop)) %>%
   group_by(chr_x, start, stop) %>%
   summarise(ID_y = toString(ID_y), pos_y = toString(pos_y)) %>%
   right_join(x)


#   chr_x start  stop ID_y           pos_y        ID_x 
#   <chr> <dbl> <dbl> <chr>          <chr>        <fct>
# 1 chr1      1    10 y1, y2         8, 9         x1   
# 2 chr1      2    20 y1, y2, y3     8, 9, 15     x2   
# 3 chr1      3    30 y1, y2, y3     8, 9, 15     x3   
# 4 chr1      4    40 y1, y2, y3, y4 8, 9, 15, 31 x4   
# 5 chr1     50   500 NA             NA           x5   
# 6 chr1     60   600 NA             NA           x6   
# 7 chr1     70   700 NA             NA           x7   
# 8 chr1     80   800 NA             NA           x8   
# 9 chrX      9    95 y9             91           x9   
#10 chrY    100  1000 NA             NA           x10  

【讨论】:

  • 非常感谢,filter()between() 提供了很好的解决方案。我会尝试使用 wohole 数据集运行它,再次感谢您!
  • 一开始它有效,但突然出现以下错误:Error in filter_impl(.data, quo) : Evaluation error: Expecting a single value: [extent=34]..该代码适合您吗?
  • 是的,它适用于我共享的数据。虽然它给了我joining factors with different levels, coercing to character vector 的警告,但那是因为你的数据中有因素。
猜你喜欢
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-30
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多