df1 <- data.frame(Chr=1, Pos= c(100,200,300,400),stringsAsFactors=F)
df2 <- data.frame(Chr=1, PosStart= c(25,25,150,175,225,275,375),PosEnd= c(150,75,275,300,400,500,750),stringsAsFactors=F)
Run Code Online (Sandbox Code Playgroud)
我想比较Pos值df1,看看是否任何的落差PosStart和PosEnd的df2.对于超过1行的情况,这可能是真的df2.在输出中,我试图将其df1$Pos作为新列附加df2$CoPos; 每次条件成立.输出应该是这样的:
Chr PosStart PosEnd CoPos
1 25 150 100
1 150 275 200
1 175 300 200
1 225 400 300
1 275 500 300
1 375 750 400
Run Code Online (Sandbox Code Playgroud)
我做过类似的事情:
for(i in 1:length(df1$Pos)){
for(j in 1:length(df2$PosStart){
df2$CoPos[j]<- df1$Pos[which(df2$PosStart[j] < df1$Pos[i] < df2$PosEnd[j])]
}
}
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我,如果没有循环,有没有办法做到这一点.我在这里做错了什么?经过几个月的挣扎,我不认为我仍然理解循环的概念.
提前感谢一堆.
你可以apply检查每一行df2:
myfun <- function(x) {
data.frame(df2[x['Pos'] < df2$PosEnd & x['Pos'] > df2$PosStart,], Pos=x['Pos'])
}
Run Code Online (Sandbox Code Playgroud)
这将返回满足条件的df2中的一行或多行以及Pos值.
> apply(df1, 1, myfun)
[[1]]
Chr PosStart PosEnd Pos
1 1 25 150 100
[[2]]
Chr PosStart PosEnd Pos
3 1 150 275 200
4 1 175 300 200
[[3]]
Chr PosStart PosEnd Pos
5 1 225 400 300
6 1 275 500 300
[[4]]
Chr PosStart PosEnd Pos
6 1 275 500 400
7 1 375 750 400
>
Run Code Online (Sandbox Code Playgroud)
然后你可以使用plyr和ldply转换为一个列表:
> library(plyr)
> ldply(apply(df1, 1, myfun), as.data.frame)
Chr PosStart PosEnd Pos
1 1 25 150 100
2 1 150 275 200
3 1 175 300 200
4 1 225 400 300
5 1 275 500 300
6 1 275 500 400
7 1 375 750 400
>
Run Code Online (Sandbox Code Playgroud)
编辑评论:
这在for循环中很难做到.你不知道你提前有多少场比赛.可能是每一行都df1匹配每一行,df2或者没有一行或两者之间.因此,您不知道您的输出需要多大.这是for loopR 中不良练习的完美例子.如果你正在增长你的输出向量而不是分配它"你将会有一个糟糕的时间mm'kay."
话虽如此,为了使你的循环工作,你需要首先使CoPos列.
df2$CoPos <- NA
Run Code Online (Sandbox Code Playgroud)
然后执行类似于循环的操作:
for (i in 1:length(df1$Pos)) {
for (j in 1:length(df2$PosStart)) {
if (df2$PosStart[j] < df1$Pos[i] & df2$PosEnd[j] > df1$Pos[i]) {
df2$CoPos[j] <- df1$Pos[i]
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您找到df1符合约束条件的两行,则只会将找到的第二行记录到相应的行中df2.
相反,你可以像这样增长一个新的data.frame:
df3 <- data.frame(Chr=1, Pos= c(100, 125, 200,300,400),stringsAsFactors=F)
out <- data.frame()
for (i in 1:length(df3$Pos)) {
for (j in 1:length(df2$PosStart)) {
if (df2$PosStart[j] < df3$Pos[i] & df2$PosEnd[j] > df3$Pos[i]) {
out <- rbind(out, cbind(df2[j,], df3$Pos[i]))
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,不要这样做......请不要:)虽然我正在传福音,但请看一下R-Inferno,以便对R中常见的陷阱进行参考.