簡體   English   中英

從 R 中的函數中更新全局環境中的嵌套列表對象

[英]Updating a nested list object in the global environment from within a function in R

以下是讓我陷入困境的一系列情況:

問題

我在 R 中編寫了一個函數,它需要在 for 循環中執行,目的是手動調整一些值,然后在全局環境中更新一個大型嵌套列表。 我有 2 個函數more.points()get.num.pts()要求用戶輸入。 這些是一個更大的函數add.points()一部分,它運行所有東西並將被包裝在一個 for 循環中。 不幸的是,我無法弄清楚如何從函數內部將嵌套列表更新到列表層次結構中的正確位置。 我必須在函數內部執行此操作,以確保我不會在函數之后的 for 循環中運行代碼行,因為這將導致readlines()失敗並將下一行代碼作為用戶輸入。 如何從add.points()函數中的正確位置更新分層列表對象? assign()似乎不能勝任這項任務,至少就我有限的知識而言。 任何幫助是極大的贊賞。 我正在制作一個用於將圖譜與大腦圖像對齊的管道,以便我可以將發出熒光的細胞定位到各自的大腦區域。

more.points <- function(){
  more.pts <- readline(prompt = "Do you need to add correspondence points to adjust the atlas registration? (y/n): ")
}

get.num.pts <- function(){
  num.pts <- readline(prompt = "How many additional points are required? (You will be able to add additional points later if you need to): ")
}

add.points <- function(){
  
  mo.pts  <- as.character(more.points());
  if(mo.pts == "y" || mo.pts == "Y" || mo.pts == "Yes" || mo.pts == "yes"){
    while(mo.pts == "y" || mo.pts == "Y" || mo.pts == "Yes" || mo.pts == "yes") {
      #ask for user input about number of new points to be created
      n.pts <- as.integer(get.num.pts());
      reg.fun.obj <- paste0(n.pts," updated!");
      print(reg.fun.obj)
      #do other stuff
#assign totally works here just fine because it isnt a hierarchical list being updated
      assign("reg.obj", reg.fun.obj, envir = .GlobalEnv);
      #Need to update the correct position in the list object hierarchy with new info.
      assign(i.data[[reference.df$i[[i]]]][[reference.df$j[[i]]]][[reference.df$k[[i]]]], reg.obj, envir = .GlobalEnv);
      #But this cannot take `i.data[[reference.df$i[[i]]]][[reference.df$j[[i]]]][[reference.df$k[[i]]]]` for the name argument. it must be a string.
      mo.pts = as.character(more.points())
    }
    
  }
  
}


可重現的例子:

這是我需要從add.points()函數中的對象更新的全局環境層次結構列表的示例:

#Hierarchical List Object Example

#The image objects have more complexity in my real implementation i.e. image_1 is itself a list object with multiple attributes.
list.i <- c("channel1", "channel2", "channel3")
list.j <- c("m1", "m2", "m3")
list.k <- c("image_1", "image_2", "image_3")
  
k.tmp <- list()
j.tmp <- list()
i.data <- list()

for(i in seq_along(list.i)){
  for(j in seq_along(list.j)){
    for(k in seq_along(list.k)){
      k.tmp[[k]] <- list.k[[k]]
      names(k.tmp)[[k]] <- paste0("img", k)
    }
    j.tmp[[j]] <- k.tmp
    names(j.tmp)[[j]] <- paste0("m", j)
    k.tmp <- list()
  }
  i.data[[i]] <- j.tmp
  names(i.data)[[i]] <- paste0("channel", i)
  j.tmp <- list
}
remove(k.tmp,j.tmp)


#Additional example list I am using to know which elements of the hierarchy need to be updated/adjusted as the for loop cycles.

reference.df <- data.frame(i = c(rep(1, 9), rep(2, 9), rep(3, 9)), j = c(rep(c(1, 1, 1, 2, 2, 2, 3, 3, 3),3)), k = c(rep(c(1, 2, 3),9)))

運行函數的代碼:

reg.obj <- i.data[[reference.df$i[[i]]]][[reference.df$j[[i]]]][[reference.df$k[[i]]]] 

for(i in seq_along(reference.df$k)){
  
  add.points()
  
}

請記住:我無法在 for 循環中的函數之后運行任何內容,因為 R 會將下一行解釋為饋送到readlines()的用戶輸入。 因此,這個循環和函數的全部意義——獲取用戶輸入、保存和循環到下一個圖像以供用戶提供輸入——將不會發生。

對於遇到此類問題的其他任何人。 不要像我一樣傻。 在您的函數中使用return()函數將您的變量轉換為輸出,您可以這樣將其輸入到嵌套列表中:在函數中:

myfun(){
#do stuff to make object containing update
return(update.obj)
}

#run the function:

list[[x]][[y]][[z]] <- myfun()

#is equivalent to below occurring outside a function:
list[[x]][[y]][[z]] <- update.obj

是的,這很愚蠢,但希望我在這里幫助某人避免了我的根本錯誤。 如果可以避免,請不要在函數中使用assign()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM