将元素附加到列表只有在它们存在的情况下。

huangapple go评论106阅读模式
英文:

Function to append elements to a list only if they exist

问题

I've created this function that puts together a list from object names, but can handle when the object doesn't exist. The function works fine on its own, but when I try and call it within another function I just get NA out for each list element. What's going on? Here's a simplified example:

我创建了这个函数,它可以从对象名称组合列表,但可以处理对象不存在的情况。这个函数单独运行正常,但当我尝试在另一个函数中调用它时,每个列表元素都变成了NA。发生了什么?以下是一个简化的示例:

genes <- c("gene1", "gene2", "gene3", "gene4")
analyses <- c("analysis_one", "analysis_two")

Function to put together a list even if an element doesn't exist

用于组合列表的函数,即使元素不存在也可以处理

append_if_exists <- function(element_names) {

Create empty list

创建一个空列表

my_list <- list()

Get and append each new element

获取并附加每个新元素

for (element_name in element_names) {

# Get new element
# 获取新元素
if (exists(element_name)) {
  element &lt;- list(get(element_name))
  names(element) &lt;- element_name
} else {
  element &lt;- list(NA)
  names(element) &lt;- element_name
}

# Append new element
# 附加新元素
my_list &lt;- c(my_list, element)

}

Output

输出

return(my_list)

}

my_function <- function(genes, analyses) {

Analysis one

分析一

if ("analysis_one" %in% analyses) {
output1 <- genes[1:3]
}

Analysis two

分析二

if ("analysis_two" %in% analyses) {
output2 <- genes[1:2]
}

Append if exists

如果存在则附加

out <- append_if_exists(c("output1", "output2"))
return(out)

}

Run the function and my list has the right names, but the elements are just 'NA'

运行函数,我的列表有正确的名称,但元素只是'NA'

result <- my_function(genes, analyses)

Run the same thing outside of the function and it works fine!

在函数外运行相同的内容,它正常工作!

output1 <- genes[1:3]
output2 <- genes[1:2]
result <- append_if_exists(c("output1", "output2"))

英文:

I've created this function that puts together a list from object names, but can handle when the object doesn't exist. The function works fine on its own, but when I try and call it within another function I just get NA out for each list element. What's going on? Here's a simplified example:

genes &lt;- c(&quot;gene1&quot;, &quot;gene2&quot;, &quot;gene3&quot;, &quot;gene4&quot;)
analyses &lt;- c(&quot;analysis_one&quot;, &quot;analysis_two&quot;)

# Function to put together a list even if an element doesn&#39;t exist
append_if_exists &lt;- function(element_names) {
  
  # Create empty list
  my_list &lt;- list()
  
  # Get and append each new element
  for (element_name in element_names) {
    
    # Get new element
    if (exists(element_name)) {
      element &lt;- list(get(element_name))
      names(element) &lt;- element_name
    } else {
      element &lt;- list(NA)
      names(element) &lt;- element_name
    }
    
    # Append new element
    my_list &lt;- c(my_list, element)
    
  }
  
  # Output
  return(my_list)
  
}

my_function &lt;- function(genes, analyses) {
  
  # Analysis one
  if (&quot;analysis_one&quot; %in% analyses) {
    output1 &lt;- genes[1:3]
  }
  
  # Analysis two
  if (&quot;analysis_two&quot; %in% analyses) {
    output2 &lt;- genes[1:2]
  }
  
  # Append if exists
  out &lt;- append_if_exists(c(&quot;output1&quot;, &quot;output2&quot;))
  return(out)
  
}

# Run the function and my list has the right names, but the elements are just &#39;NA&#39;
result &lt;- my_function(genes, analyses)

# Run the same thing outside of the function and it works fine!
output1 &lt;- genes[1:3]
output2 &lt;- genes[1:2]
result &lt;- append_if_exists(c(&quot;output1&quot;, &quot;output2&quot;))

答案1

得分: 1

不需要回答我要翻译的问题。以下是翻译的内容:

与编写自己的append_if_exists不同,只需使用内置的mget()函数。如果要避免不存在的名称,可以将名称与当前范围中的名称相交。这应该可以工作。

问题在于您的解决方案需要注意对象被找到的环境。R使用词法作用域,因此函数在定义函数的环境中解析变量,而不是在调用函数的环境中。如果您在全局环境中定义了append_if_exists,那么它无法看到在my_function运行时环境中定义的output1output2get()函数确实有一个envir=参数,所以您可以将适当的环境传递给该函数,但这可能会很快变得混乱。

英文:

Rather than write your own append_if_exists, just use the built in mget() function. If you want to avoid names that don't exist, intersect the names with the names in the current scope. This should work

my_function &lt;- function(genes, analyses) {
  ...

  out &lt;- mget(intersect(c(&quot;output1&quot;, &quot;output2&quot;), ls()))
  return(out)
}

The problem with your solution is that you need to pay attention to the environment where objects are found. R uses lexical scoping, so functions resolve variables in the environment where the function was defined, not where it was called. If you define append_if_exists in the global environment, then it can't see output1 and output2 which are defined in the my_function runtime environment. The get() function does have an envir= parameter so you could pass in the appropriate environment to the function but that would get messy quickly.

huangapple
  • 本文由 发表于 2023年8月5日 04:46:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76839028.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定