75

我需要访问 lapply 函数中的列表名称。我在网上找到了一些线程,据说我应该遍历列表的名称,以便能够在我的函数中获取每个列表元素名称:

> n = names(mylist)
> mynewlist = lapply(n, function(nameindex, mylist) { return(mylist[[nameindex]]) }, mylist)
> names(mynewlist)
NULL
> names(mynewlist) = n

问题是 mynewlist 丢失了原始的 mylist 索引,我必须添加 last names() 分配来恢复它们。

有没有办法为 lapply 函数返回的每个元素提供一个明确的索引名称?或者另一种方法来确保 mynewlist 元素设置了正确的索引名称?如果 lapply 不以与 mylist 相同的顺序返回列表元素,我觉得 mynewlist 索引名称可能是错误的。

4

6 回答 6

76

我相信lapply默认情况下会保留您正在迭代的任何内容的名称属性。当您存储 in 的名称时myListn该向量不再具有任何“名称”。因此,如果您将其添加回通过,

names(n) <- names(myList)

lapply以前一样使用,你应该得到想要的结果。

编辑

今天早上我的大脑有点模糊。这是另一个可能更方便的选项:

sapply(n,FUN = ...,simplify = FALSE,USE.NAMES = TRUE)

我一直在摸索,很困惑,lapply没有USE.NAMES争论,然后我实际上查看了代码sapply并意识到我很傻,这可能是一个更好的方法。

于 2012-02-27T18:12:18.233 回答
46

setNames函数在这里是一个有用的快捷方式

mylist <- list(a = TRUE, foo = LETTERS[1:3], baz = 1:5)
n <- names(mylist)
mynewlist <- lapply(setNames(n, n), function(nameindex) {mylist[[nameindex]]})

保留名称

> mynewlist
$a
[1] TRUE

$foo
[1] "A" "B" "C"

$baz
[1] 1 2 3 4 5
于 2013-08-29T20:31:03.207 回答
7

以joran的回答为基础,并对其进行精确化:

包装器sapply(USE.NAMES=T)确实会将您正在迭代的向量的值设置为最终结果的名称(而不是其名称属性,如 lapply),但前提是这些是字符。

结果,传递索引将无济于事。如果要使用 传递索引sapply,则需要使用一些(丑陋的)强制转换:

sapply(as.character(c(1,11)), function(i) TEST[[as.numeric(i)]], USE.NAMES = TRUE)

在这种情况下,更简洁的解决方案是直接设置和使用原始对象的名称。以下是详尽的解决方案列表:

TEST <- as.list(LETTERS[1:12])

### lapply ##
## Not working because no name attribute
lapply(c(1,11), function(i) TEST[[i]])

## working but cumbersome
index <- c(1,11)
names(index) <- index
lapply(index, function(i) TEST[[i]])

### sapply ##
## Not working because vector elements are not strings
sapply(c(1,11), function(i) TEST[[i]], simplify = F) 

## Working with the casting trick
sapply(as.character(c(1,11)), function(i) TEST[[as.numeric(i)]], simplify = F)

## Cleaner, using names with sapply:
names(TEST) <- LETTERS[26:15] 
sapply(names(TEST)[c(1,11)], function(name) TEST[[name]], simplify = F) 
于 2013-08-29T17:58:22.807 回答
7

imap()purrr包装中可以很好地解决您的问题。

library(purrr)
mylist <- list(foo1=1:10,foo2=11:20)
imap(mylist, function(x, y) mean(x)) ## x is the value, y is the name

或者您可以使用更紧凑的 imap 版本:

imap(mylist, ~ mean(.x))

请注意,您可以根据所需的矢量类型使用 imap_xxx 的变体:

imap_dbl(mylist, ~ mean(.x)) ## will return a named numeric vector. 
于 2017-11-07T20:08:24.283 回答
6

llply()从包裹里看了plyr吗?

它完全符合您的要求。对于列表的每个元素,应用函数,将结果保存为列表。llply 与 lapply 等价,只是它会保留标签并可以显示进度条。?llply

mylist <- list(foo1=1:10,foo2=11:20)
>names(mylist)
[1] "foo1" "foo2"
newlist<- llply(mylist, function(x) mean(x))

>names(newlist)
[1] "foo1" "foo2"
于 2012-02-28T01:06:38.857 回答
0

同样基于@joran的答案,您可以编写一个保留对象属性的包装函数,如下所示:

lapply_preserve_names <- function(list, fun){
  lapply(seq_along(list), function(i) {
    obj = list[i]
    names(obj) = names(list)[i]
    fun(obj)
  })
}

然后不要使用 lapply,只需使用lapply_preserve_names(your_list, function)

于 2020-01-28T15:16:45.763 回答