在lapply函数中访问和保留列表名称

Rob*_*ick 51 r names lapply

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

> n = names(mylist)
> mynewlist = lapply(n, function(nameindex, mylist) { return(mylist[[nameindex]]) }, mylist)
> names(mynewlist)
NULL
> names(mynewlist) = n
Run Code Online (Sandbox Code Playgroud)

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

有没有办法为lapply函数返回的每个元素提供显式索引名称?或者以不同的方式确保mynewlist元素具有正确的索引名称集?如果lapply没有以与mylist相同的顺序返回列表元素,我觉得mynewlist索引名称可能是错误的.

jor*_*ran 50

我相信lapply默认情况下会保留您迭代的任何名称属性.当您存储myListin 的名称时n,该向量不再具有任何"名称".所以如果你把它添加回来,

names(n) <- names(myList)
Run Code Online (Sandbox Code Playgroud)

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

编辑

今天早上我的大脑有点模糊.这是另一个,也许更方便的选择:

sapply(n,FUN = ...,simplify = FALSE,USE.NAMES = TRUE)
Run Code Online (Sandbox Code Playgroud)

我正在摸索,困惑,lapply没有USE.NAMES争论,然后我实际看了代码,sapply并意识到我是愚蠢的,这可能是一个更好的方式去.

  • @joran我使用了sapply并且能够输出.但你能解释一下为什么你说"然后我真的看了一下`sapply`的代码,并意识到我很傻"?那么为什么"lapply"没有"USE.NAMES"? (5认同)
  • 你可以用 `names(n) &lt;- n` 替换第二个。 (3认同)

Bri*_*ggs 40

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

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

它保留了名字

> mynewlist
$a
[1] TRUE

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

$baz
[1] 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)


Mai*_*ura 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"
Run Code Online (Sandbox Code Playgroud)

  • 嗯 看起来就像“ lapply”所做的一样。例如参见`lapply(mylist,mean)`和`llply(names(mylist),function(x)mean(mylist [[x]])))。有什么想法“保留标签”是什么意思? (2认同)

Ant*_*zée 6

以朱兰的答案为基础,并将其精确化:

sapply(USE.NAMES=T)包装的确会设定为最终结果的矢量的值你迭代(而不是它的名称属性像lapply)的名字,但只有当这些字符.

因此,传递指数无济于事.如果你想传递索引sapply,你需要求助于某些(丑陋的)转换:

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

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

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) 
Run Code Online (Sandbox Code Playgroud)


Kev*_*rca 6

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
Run Code Online (Sandbox Code Playgroud)

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

imap(mylist, ~ mean(.x))
Run Code Online (Sandbox Code Playgroud)

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

imap_dbl(mylist, ~ mean(.x)) ## will return a named numeric vector. 
Run Code Online (Sandbox Code Playgroud)