我有一个递归函数,由@thothal here友好地向我解释,它允许我根据在父dataframe中查找一个字符串来递归地获取数据格式。通过我提供的示例,这是很好的工作。
但是,我现在正在研究进一步的表,在这些表中,子元素存在于父表中,反之亦然。这导致递归函数中有一个无穷大的循环。
若要重复原来的问题,请更改:
Numsdf1<-c("C123","C456","C789")
Textdf1<-c("Harry","Bobby","Terry")
df1<-data.frame(Numsdf1,Textdf1,stringsAsFactors=FALSE)第二个数据是查找字符串"C123“的结果。
NumsC123<-c("C123","Noo","Too")
TextC123<-c("Tim","Slim","Shim")
C123<-data.frame(NumsC123,TextC123,stringsAsFactors=FALSE)第三个数据是查找“首席运营官”的结果。
NumsCoo<-c("S144","S199","S743")
TextCoo<-c("Ellie","Bellie","Tellie")
Coo<-data.frame(NumsCoo,TextCoo,stringsAsFactors=FALSE)第四是查找"Noo“的结果。
NumsNoo<-c("GHS","THE","PAA")
TextNoo<-c("Front","Bunt","Shunt")
Noo<-data.frame(NumsNoo,TextNoo,stringsAsFactors=FALSE)最初的解决办法是:
library(tidyverse)
get_all_dfs <- function(df) {
   lapply(df[, 1], function(elem) {
      print(paste("Looking for element", elem))
      # use mget because we can use ifnotfound despite we are requesting only one element
      next_df <- mget(elem, env = .GlobalEnv, ifnotfound = NA)
      if (!is.na(next_df)) {
         unlist(get_all_dfs(next_df[[1]]), F)
      } else {
         list(setNames(df, c("col1", "col2")))
      }
    })
}
flatten_dfr(get_all_dfs(df1)) %>% unique()这意味着,当我运行这个函数时,我会得到一个循环,而这个循环是我无法脱离的。因此,而不是预期的结果:
C123 -> Coo -> S144 -> S199 -> S743 -> Noo -> GHS -> THE -> PAA -> Too -> C456 -> C789我得到了
C123 -> Coo -> C123 -> Coo -> C123 etc.我能做些什么来防止这件事?
更新1
我从@thothal实现了这个解决方案。我遇到的问题是,我使用的查找函数返回一个dataframe,而不是一个列表,所以我也创建了一个列表来存储全局环境。然而,循环仍在发生。以下是更新的代码:
   get_all_dfs_rec <- function(df, my_env) {
        lapply(df$relatedIdEx, function(elem) {
            print(paste("Looking for element", elem))
            next_df <- myGIConcepts(elem) ###This returns a dataframe
            next_df<-list(next_df,my_env) ###Environment variable kept in a list
        if (!is.na(next_df)) {
          rm(list = elem, envir = my_env)
          unlist(get_all_dfs_rec(next_df[[1]], my_env), FALSE)
          } else {
          list(setNames(df, c("col1", "col2")))
        }
    })
  }
        
    get_all_dfs <- function(df_start) {
  ## create a new environment
  my_env <- new.env()
  ## and add all 'data.frames' from the global environment to it
  walk(ls(.GlobalEnv), ~ {
    elem <- get(.x, env = .GlobalEnv);
    if (class(elem) == "data.frame") my_env[[.x]] <- elem})
  flatten_dfr(get_all_dfs_rec(df_start, my_env)) %>% unique()
}发布于 2019-02-28 08:55:31
您可以将所有数据帧放在自己的环境中,一旦找到它们,就将其从其中移除:
get_all_dfs_rec <- function(df, my_env) {
   lapply(df[, 1], function(elem) {
      print(paste("Looking for element", elem))
      # use mget because we can use ifnotfound despite we are requesting only one element
      next_df <- mget(elem, env = my_env, ifnotfound = NA)
      if (!is.na(next_df)) {
         # use list, otherwise rm tries to remove elem (which does not exist in the env)
         rm(list = elem, envir = my_env)
         unlist(get_all_dfs_rec(next_df[[1]], my_env), FALSE)
      } else {
         list(setNames(df, c("col1", "col2")))
      }
    })
}
get_all_dfs <- function(df_start) {
   ## create a new environment
   my_env <- new.env()
   ## and add all 'data.frames' from the global environment to it
   walk(ls(.GlobalEnv), ~ {
       elem <- get(.x, env = .GlobalEnv); 
       if (class(elem) == "data.frame") my_env[[.x]] <- elem})
   flatten_dfr(get_all_dfs_rec(df_start, my_env)) %>% unique()
}https://stackoverflow.com/questions/54912421
复制相似问题