迭代两个列表的有效方法(嵌套循环替代)

时间:2016-10-24 16:17:38

标签: r list nested-loops lapply

我有两个数据框,SCR和SpecificSpecies。 SCR中物品的名称部分包含特定物种中列出的物种。

SpecificSpecies$Species
S cerevisiae
Daucus carota

SCR$MESH_HEADINGS
tetracycline CMT-3 
zrg17 protein, S cerevisiae
EP4 glycoprotein, Daucus carota

我正在尝试获取SCR的子集,其中只包含那些没有任何匹配物种的条目。在上面的例子中,该列表只是

tetracycline CMT-3.

我学会这样做的方法是使用嵌套循环,将SCR中的每个条目与SpecificSpecies中的每个条目进行比较。如果未找到匹配项,请将SCR行附加到新表:

For each row in SCR {
  SpeciesNumber <- 1
  match <-NULL
  while ((is.null(match)) & (SpeciesNumber < length(SpecificSpecies$Species))) {
  if (grepl(SpecificSpecies$Species[SpeciesNumber], SCR[row,]$MESH_HEADING)){
    match <- TRUE}
  SpeciesNumber <- SpeciesNumber + 1}
  if ((is.null(match) & SpeciesNumber == length(SpecificSpecies$Species)) {
    speciesNoMatch = rbind(speciesNoMatch, SCR[row])}
}}

但这种情况非常缓慢,SCR中有65,000个条目,而SpecificSpecies中大约有1500个条目。有没有办法像lapply这样嵌套?或者其他一些对我不熟悉有帮助的功能?

我确定这是一个糟糕的代码。我是医学图书管理员,有时候必须使用R进行数据分析,所以我的编程技能非常有限,但是如果我的解决方案很难或效率低下,只要它们最终起作用,那通常并不重要。 。我知道必须有更好的方法来做到这一点;原谅我不知道可能是一个简单的解决方案。

2 个答案:

答案 0 :(得分:0)

我认为!(%in%)可以解决问题:

SpecificSpecies <- data.frame(
  Species = c("S cerevisiae", "Daucus carota"),
  stringsAsFactors = FALSE
)

SCR <- data.frame(
  MESH_HEADINGS = c("tetracycline CMT-3", "zrg17 protein", "S cerevisiae", 
                    "EP4 glycoprotein", "Daucus carota"),
  stringsAsFactors = FALSE
)


SCR[!(SCR$MESH_HEADINGS %in% SpecificSpecies$Species), , drop = FALSE]
#        MESH_HEADINGS
# 1 tetracycline CMT-3
# 2      zrg17 protein
# 4   EP4 glycoprotein

, , drop = ...不是一个错字。第一个,确保返回所有列/变量。第二个, drop = FALSE确保返回的结果仍然是数据框。

校正

好的,我刚刚注意到您正在grep寻找Species。以下代码应该有效:

SpecificSpecies <- data.frame(
  Species = c("S cerevisiae", "Daucus carota"),
  stringsAsFactors = FALSE
)

SCR <- data.frame(
  MESH_HEADINGS = c("tetracycline CMT-3",
                    "zrg17 protein, S cerevisiae", 
                    "EP4 glycoprotein, Daucus carota"),
  stringsAsFactors = FALSE
)

matching <- lapply(SpecificSpecies$Species, function(x) {
  grep(x, SCR$MESH_HEADINGS)
})

SCR[-(unlist(matching)), ]
#        MESH_HEADINGS
# 1 tetracycline CMT-3

lapply()使用匿名函数来识别模式匹配。它遍历每个物种并将其与每个SCR$MESH_HEADINGS物品进行比较。它返回匹配索引的列表。

子集([])只是在匹配的索引首先-之后删除匹配的索引(unlist),以使其与子集函数兼容。 / p>

答案 1 :(得分:0)

主要想法:

在SpecificSpecies上执行循环,因为它的行数较少。 由于SCR数据帧将减少,所以递归执行,因此循环每次都会处理较少的数据。

通常,包data.tableplyr会提高效果。 这是data.table

的解决方案
    library(data.table)
SpecificSpecies <- data.frame(Species = c("S cerevisiae", "Daucus carota"),stringsAsFactors = FALSE)
SCR <- data.frame(MESH_HEADINGS = c("tetracycline CMT-3", "zrg17 protein, S cerevisiae","EP4 glycoprotein Daucus carota"),stringsAsFactors = FALSE)

dt_temp <- data.table(SCR)
for (species in SpecificSpecies$Species) {
  dt_temp <- dt_temp[!grepl(species,dt_temp$MESH_HEADINGS), ]
}
dt_result <- dt_temp
dt_result