如何绕过嵌套的for循环?

时间:2018-03-29 06:09:41

标签: r loops

所以情况是这样的: 我基本上有一个数据框,其中包含大约100,000行数据。我对特定的数据列POS感兴趣,我想检查POS的值是否在另一个数据框的两个值之间,即开始和结束,并跟踪那些数据的实例数。

例如,在我的第一个数据框中,我有类似

的内容
.componentHolder {
  width: 100px;
  height: 120px;
  border: 1px solid black;
  padding: 0px;
  margin: 0px;
  float: left; // I used float instead of inline-block
}

在我的其他数据框中,我有像

这样的东西
ID POS  
A   20  
B   533  
C   600 

我想知道POS中有多少项在START-END范围内。所以在这种情况下,有两个项目。另外,如果可能的话,我也可以在开始和结束之间获得POS的ID吗?

如何在不使用嵌套for循环的情况下进行此操作?

4 个答案:

答案 0 :(得分:6)

这是一个在数据库环境中可能发生的相当常见的问题。以下是使用sqldf的解决方案:

library(sqldf)

query <- "SELECT POS, ID FROM df1 INNER JOIN df2 "
query <- paste0(query, "ON df1.POS BETWEEN df2.START AND df2.END")
sqldf(query)

如果第二个数据框中的范围可能重叠,则上述查询可能会返回给定POS值的多个结果。在这种情况下,请将SELECT POS替换为SELECT DISTINCT POS

答案 1 :(得分:6)

我们可以使用data.table

的非等联接
library(data.table)
setDT(df1)[df2, on = .(POS > START, POS <= END)][, sum(!is.na(ID))]
#[1] 2

答案 2 :(得分:1)

我们可以使用mapply中的base-R作为:

来实现相同目标
df1[mapply(function(x)any(x >= df2$START & x <= df2$END),df1$POS),]
#  ID POS
#2  B 533
#3  C 600

数据

df1 <- read.table(text = 
"ID POS  
A   20  
B   533  
C   600", header = T)


df2 <- read.table(text = 
"START      END  
123        150  
489        552  
590        600", header = TRUE)

答案 3 :(得分:1)

数据框:main

ID POS  
A   20  
B   533  
C   600 

数据框:ran

START   END  
123     150  
489     552  
590     600

简单的sapply应该足以满足您的使用案例:

sapply(main$POS, function(x) { sum(x>=ran$START & x<=ran$END) })

将返回:

[1] 0 1 1

您可以将其绑定回main数据框中的新列:

main$Count <- sapply(main$POS, function(x) { sum(x>=ran$START & x<=ran$END) }))

  ID POS count
1  A  20     0
2  B 533     1
3  C 600     1

这也适用于重叠范围。