[英]Crossing multiple data frames in R
StackOverflow question StackOverflow问题
Hello fellows, 大家好
I am trying to "cross" multiple dataframes with R. 我试图用R“交叉”多个数据框。
My data frames are coming from a high-throughput sequencing experiments and look like the followings : 我的数据帧来自高通量测序实验,如下所示:
df1 : df1:
chr pos orient weight in_nucleosome in_subtelo
1 NC_001133 999 + 1 TRUE TRUE
2 NC_001133 1505 - 14 FALSE TRUE
3 NC_001133 1525 - 2 TRUE TRUE
4 NC_001134 480 + 1 TRUE TRUE
5 NC_001134 509 + 2 FALSE TRUE
6 NC_001134 539 + 3 FALSE TRUE
7 NC_001135 1218 + 1 TRUE TRUE
8 NC_001135 1228 + 2 TRUE TRUE
9 NC_001135 1273 + 1 TRUE TRUE
10 NC_001136 362 + 1 TRUE TRUE
and 和
df2: df2:
chr feature start end orient
1 NC_001133 ARS 707 776 .
2 NC_001133 ARS 7997 8547 .
3 NC_001133 ARS 30946 31183 .
4 NC_001133 ARS_consensus_sequence 31002 31018 +
5 NC_001133 ARS_consensus_sequence 70418 70434 -
6 NC_001133 ARS_consensus_sequence 124463 124479 -
7 NC_001136 blocked_reading_frame 721071 721481 -
8 NC_001137 blocked_reading_frame 375215 377614 -
9 NC_001141 blocked_reading_frame 29032 30048 +
10 NC_001133 CDS 335 649 +
What I want to do is to know for a given chromosome ("chr" here) and for each df2$feature whether or not (df2$start < df1$pos < df2$end). 我想做的是知道给定染色体(此处为“ chr”)以及每个df2 $功能是否(df2 $ start <df1 $ pos <df2 $ end)。 I would then like to add a column to df1 whose name would be the one of the considered df2feature and filled with TRUE or FALSE in respect to the condition stated earlier.
然后,我想在df1中添加一列,该列的名称将是考虑的df2feature之一,并针对上述条件用TRUE或FALSE填充。
I am pretty sure that the apply family of function have to be used maybe nested in one antoher but after hours of trying I can't manage to do it. 我很确定必须将应用函数族嵌套在另一个容器中,但是经过数小时的尝试,我还是无法做到这一点。
I did it in a very inelegant, long and error prone way with nested for loops but I am convinced there is a better simpler and maybe faster solution. 我使用嵌套的for循环以非常优雅,容易出错的方式进行了此操作,但是我坚信有更好,更简单,甚至更快的解决方案。
Thank you for reading this, 谢谢您阅读此篇,
Antoine. 安托万
Though it may be possible with dplyr
(I tried but am not that proficient), I got it to work (I think) with foreach
and iterators
: 尽管使用
dplyr
可能是可行的(我尝试过但不熟练),但我认为它可以与foreach
和iterators
一起使用(我认为):
Your data: 您的数据:
df1 <- structure(list(chr = c("NC_001133", "NC_001133", "NC_001133", "NC_001134", "NC_001134", "NC_001134", "NC_001135", "NC_001135", "NC_001135", "NC_001136"),
pos = c(999L, 1505L, 1525L, 480L, 509L, 539L, 1218L, 1228L, 1273L, 362L),
orient = c("+", "-", "-", "+", "+", "+", "+", "+", "+", "+"),
weight = c(1L, 14L, 2L, 1L, 2L, 3L, 1L, 2L, 1L, 1L),
in_nucleosome = c(TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE),
in_subtelo = c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)),
.Names = c("chr", "pos", "orient", "weight", "in_nucleosome", "in_subtelo"),
class = "data.frame",
row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"))
df2 <- structure(list(chr = c("NC_001133", "NC_001133", "NC_001133", "NC_001133", "NC_001133", "NC_001133", "NC_001136", "NC_001137", "NC_001141", "NC_001133"),
feature = c("ARS", "ARS", "ARS", "ARS_consensus_sequence", "ARS_consensus_sequence", "ARS_consensus_sequence", "blocked_reading_frame", "blocked_reading_frame", "blocked_reading_frame", "CDS"),
start = c(707L, 7997L, 30946L, 31002L, 70418L, 124463L, 721071L, 375215L, 29032L, 335L),
end = c(776L, 8547L, 31183L, 31018L, 70434L, 124479L, 721481L, 377614L, 30048L, 649L),
orient = c(".", ".", ".", "+", "-", "-", "-", "-", "+", "+")),
.Names = c("chr", "feature", "start", "end", "orient"),
class = "data.frame",
row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"))
Since I think your data does not have any matches, I'll inject some: 由于我认为您的数据没有任何匹配项,因此我将注入一些数据:
## to be able to find *something*
df1$pos <- c(999, 1505, 8000, 480, 509, 539, 1218, 1228, 1272, 721072)
The code: 编码:
library(foreach)
library(iterators)
## pre-populate df1 with necessary columns
for (col in unique(df2$feature)) df1[,col] <- FALSE
df1a <- foreach (subdf1 = iter(df1, by='row'), .combine=rbind) %do% {
features <- unique(df2$feature[df2$chr== subdf1$chr])
for (feature in features) {
idx <- (df2$chr == subdf1$chr) & (feature == df2$feature)
if (length(idx)) {
subdf1[feature] <- any((df2$start[idx] < subdf1$pos) & (subdf1$pos < df2$end[idx]))
}
}
subdf1
}
df1a
## chr pos orient weight in_nucleosome in_subtelo ARS
## 1 NC_001133 999 + 1 TRUE TRUE FALSE
## 2 NC_001133 1505 - 14 FALSE TRUE FALSE
## 3 NC_001133 8000 - 2 TRUE TRUE TRUE
## 4 NC_001134 480 + 1 TRUE TRUE FALSE
## 5 NC_001134 509 + 2 FALSE TRUE FALSE
## 6 NC_001134 539 + 3 FALSE TRUE FALSE
## 7 NC_001135 1218 + 1 TRUE TRUE FALSE
## 8 NC_001135 1228 + 2 TRUE TRUE FALSE
## 9 NC_001135 1272 + 1 TRUE TRUE FALSE
## 10 NC_001136 721072 + 1 TRUE TRUE FALSE
## ARS_consensus_sequence blocked_reading_frame CDS
## 1 FALSE FALSE FALSE
## 2 FALSE FALSE FALSE
## 3 FALSE FALSE FALSE
## 4 FALSE FALSE FALSE
## 5 FALSE FALSE FALSE
## 6 FALSE FALSE FALSE
## 7 FALSE FALSE FALSE
## 8 FALSE FALSE FALSE
## 9 FALSE FALSE FALSE
## 10 FALSE TRUE FALSE
An easy side-effect of using foreach
and iterators
is that, if the data is large and you use doParallel
, just replace %do%
with %dopar%
and things go as parallel as you define. 使用
foreach
和iterators
一个简单的副作用是,如果数据很大并且使用了doParallel
,只需将%do%
替换为%dopar%
,事情就可以按照您定义的进行。 You could preface all of the above with something like: 您可以使用类似以下内容的开头:
library(doParallel)
cl <- makeCluster(detectCores() - 1) # leaving one available is "A Good Thing (tm)"
registerDoParallel(cl)
## replace %do% with %dopar%, do all of the above code
## clean up
stopCluster(cl)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.