从for循环中删除列表中的元素

4

我有一个名为列表的列表(包含数据框)。

l_of_lists <- list(
  fruits = list(
      red = data.frame("apple", "cherry", "strawberry"),
      yellow = data.frame("banana", "lemon"),
      orange = data.frame("orange", "grapefruit", "blood orange")),
  colors = list(
      green = data.frame("light green", "green", "dark green"),
      red = data.frame("red", "dark red"),
      blue = data.frame("light blue", "blue", "dark blue")),
  places = list(
    inside = data.frame("living room", "bathrooom", "kitchen"),
    outside = data.frame("garden", "yard"),
    neighborhood = data.frame("playground", "shop", "school"))
  )

我正在循环遍历的,以确定每个数据框的列数,并且我想删除不满足条件的每个(在本例中是拥有三列)。使用以下代码:
for (ls in l_of_lists){
  for (sublist in ls){
    if (!ncol(sublist) == 3)
    {
      print(ncol(sublist))
      #sublist <- NULL # this does achieve the desired result
    }
  }
}

我该如何删除符合条件的子列表? (我相信有更有效的方法来完成此操作,如果您有提示,请告诉我。)

2
这个代码不如你期望的工作的原因是由于循环内的对象sublist并不是指向l_of_lists中原本对象的指针,而是在每次循环周期内创建一个全新的对象(然后将其赋值为NULL)。 - rookie
2个回答

6
更简单的方法是称呼没有3列的元素:
lapply(l_of_lists,function(i)i[sapply(i,length)==3])

使用sapply函数,遍历l_of_list的每个元素并获取其列数,然后使用此结果筛选出仅有3列的子集。如果想要删除,请尝试以下方法。
l_of_lists = lapply(l_of_lists,function(i)i[sapply(i,length)==3])

2
虽然我认为这是最好的解决方案,但它并没有回答关于在for循环中删除项目的具体问题。 - rookie
在R中,@rookie经常使用for循环来迭代对象,但这种方式并不是最清晰或最有效的方法,因为它们忽略了R的向量化特性。通常情况下,通过将循环替换为类似于*apply函数的东西,可以显著提高提问者的尝试水平。 - camille
嘿@rookie,是的,我应该解释一下为什么它不起作用。在这个例子中,将其设置为NULL不起作用,因为sublist是一个新对象。你需要回到原始列表,例如,l_of_lists[[1]][[2]] <- NULL,这就是你的解决方案 :) 我总是觉得子集比删除更容易。因此,我提供了那个解决方案。 - StupidWolf
2
@camille 我从未说过它们是...我只是指出这个答案没有回答问题,问题是想了解关于for循环的知识。我还说这比使用for循环更好的解决方案。你有什么困惑吗? - rookie
@StupidWolf 是的,这会很有帮助,特别是对于那些可能遇到这个问题并不确定为什么你的解决方案更好的人...顺便说一下,这与“高效迭代对象”没有任何关系 :) - rookie
1
@camille 也要注意,在大多数情况下,使用 *apply 函数并不能保证向量化。在大多数情况下,lapply 只是一个 for 循环的包装器。在这里查看更多信息:http://adv-r.had.co.nz/Functionals.html - rookie

5

如果你想使用循环,最好使用索引而不是对象:

for (i in 1:length(l_of_lists)){
  sublist = l_of_lists[[i]]
  for (j in 1:length(sublist)){
    obj = sublist[[j]]
    if (!ncol(obj) == 3)
    {
      print(ncol(obj))
      l_of_lists[[i]][[j]] <- NULL # this does achieve the desired result
    }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接