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)
我正在尝试比较Pos
中的df1
值,以查看PosStart
与PosEnd
之间的df2
和df2
之间的差异。对于超过1行的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
;每次条件成立。输出应该像:
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])]
}
}
我做过类似的事情:
{{1}}
有人可以告诉我是否有办法在没有循环的情况下执行此操作。我在这里做错了什么?经过几个月的挣扎,我不认为我仍然理解循环的概念。
提前感谢一大堆。
答案 0 :(得分:5)
您可以apply
检查df2
的每一行:
myfun <- function(x) {
data.frame(df2[x['Pos'] < df2$PosEnd & x['Pos'] > df2$PosStart,], Pos=x['Pos'])
}
将返回满足条件的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
>
然后您可以使用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
>
编辑评论:
这在for循环中很难做到。你不知道你提前有多少场比赛。可能是df1
中的每一行都匹配df2
中的每一行,或者没有任何一行或其中的任何一行。因此,您不知道您的输出需要多大。这是R中糟糕的for loop
练习的完美例子。如果你正在增长你的输出向量而不是分配它“你将会有一个糟糕的时间mm'kay。”
话虽如此,为了让你的循环工作,你需要先建立CoPos
列。
df2$CoPos <- NA
然后执行与你的循环类似的东西:
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]
}
}
}
但是,如果您在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]))
}
}
}
但是,不要这样做......请不要:)虽然我正在传福音,但请查看R-Inferno以获得有关R中常见陷阱的绝佳参考。
答案 1 :(得分:3)
虽然@Justin answer适用于这种情况,但如果您不记得apply
,则在data.frame上使用apply
会导致混淆错误{1}}会在每行/每列调用FUN
之前将您的data.frame转换为矩阵。
这是一个更通用的解决方案,可以避免这个潜在的问题:
compareFun <- function(x) {
data.frame(df2[x > df2$PosStart & x < df2$PosEnd,], Pos=x)
}
do.call(rbind, lapply(df1$Pos, compareFun))
详细说明,如果df1
和df2
定义为Chr
是角色,Justin的解决方案会抛出一个错误,但不清楚引起了这个问题:
df1 <- data.frame(Chr="1", Pos=c(100,200,300,400), stringsAsFactors=FALSE)
df2 <- data.frame(Chr="1", PosStart=c(25,25,150,175,225,275,375),
PosEnd=c(150,75,275,300,400,500,750), stringsAsFactors=FALSE)
apply(df1, 1, myfun)
# Error in data.frame(df2[x["Pos"] < df2$PosEnd & x["Pos"] > df2$PosStart, :
# arguments imply differing number of rows: 0, 1