2012-02-27 79 views
34

我需要訪問lapply函數內的列表名稱。我在網上找到了一些線程在那裏的說我應該在列表中的名稱重複,以能在我的函數來獲取每個列表元素名稱:訪問並保存lapply函數中的列表名稱

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

的問題是,mynewlist失去原有MYLIST指標,我必須添加最後的名稱()分配來恢復它們。

有沒有辦法給lapply函數返回的每個元素提供一個顯式的索引名?或者確保mynewlist元素具有正確的索引名稱集的另一種方法?如果lapply沒有以與mylist相同的順序返回列表元素,我感覺mynewlist索引名稱可能是錯誤的。

回答

33

我相信lapply在默認情況下會保留您正在迭代的任何名稱屬性。當您將名稱myList存儲在n中時,該向量不再具有任何「名稱」。所以,如果你像以前一樣添加在經由背部,

names(n) <- names(myList) 

和使用lapply,你應該得到期望的結果。

編輯

我的腦子今天早上有點雲裏霧裏。下面是另一個,也許更方便,選項:

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

我摸索,混淆起來,lapply沒有一個USE.NAMES說法,然後我其實看的sapply代碼,並意識到,我是傻了,這可能是一個更好的方法。

+0

沒錯,這工作。我仍然需要通過n =個名稱(myList)創建'n'。兩次調用名字(myList),一次創建n,第二次設置n個屬性。 – 2012-02-27 18:31:05

+1

雖然你可以用'names(n)< - n'代替第二個。 – Aaron 2012-02-27 18:43:39

+0

@RobertKubrick看到我的編輯可能更好的解決方案。檢查'sapply'的代碼,看看這是多麼簡單;它只是作爲一個包裝,在事後添加名稱。 – joran 2012-02-27 18:51:55

5

您是否從包plyr看過llply()

它完全符合你的要求。 對於列表中的每個元素,應用函數,將結果保存爲列表。 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" 
+0

嗯。這看起來正是'lapply'所做的。參見例如'lapply(mylist,mean)'和'llply(names(mylist),function(x)mean(mylist [[x]]))''。任何想法「保護標籤」意味着什麼? – Aaron 2012-02-28 01:49:20

+0

我認爲'mlply'會做到這一點 – baptiste 2012-02-28 06:16:28

4

大廈joran的答案,precising它:

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) 
32

setNames功能在這裏有用的快捷方式

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

purrr包保留名稱

> mynewlist 
$a 
[1] TRUE 

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

$baz 
[1] 1 2 3 4 5 
1

imap()是您不錯問題。

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. 
相關問題