2013-07-06 23 views
17

我有兩個向量,我想在R中創建一個列表,其中一個向量是鍵,另一個是值。我以爲我會很容易地找到答案在我的書或谷歌周圍,我期待找到一個解決方案,如向名稱添加名稱(名稱(v)< - names_vector),但我失敗了。如何在兩個向量中創建R中的列表(一個是鍵,另一個是值)?

我已經來了兩種可能的解決方案,但他們都沒有看起來優雅。 R不是我的主要編程語言,但我認爲R是實用的更好的解決方案應該存在(如list(keys = x,values = y))。

我的解決方法1:經典的循環解決方案:

> xx <- 1:3 
    > yy <- letters1:3 
    > zz =list() 
    >for(i in 1:length(yy)) {zz[[yy[i]]]<-xx[i]} 

我的解決方案2:通過名爲向量間接路徑:

> names(xx) <- letters[1:3] 
    > as.list(xx) 

看來,我有一個解決辦法,但我的向量具有百萬或更多元素,我不僅擔心編碼風格(對我很重要),而且還擔心效率(但我不知道如何在R中進行分析)。有沒有更適當的方法來做到這一點?使用指定的矢量快捷方式是否是一種很好的做法?

[[UPDATE]]我的applogies,可能我簡化了問題,使其可重現。我想給列表中的元素命名。我首先嚐試了names(),但似乎我做了錯誤的事情,並沒有奏效。所以我得到了錯誤的想法,名稱()不適用於列表。但他們確實做如圖接受的答案

+0

你說 「1萬組以上的元素(即是大對象)」?你能確定你的對象的結構,以瞭解它有多大? – agstudy

+0

@agstudy我認爲這是因爲OP由於元素的數量而將矢量描述爲大對象,而不是元素本身作爲大對象?儘管如此,要將兩個向量組合在一個列表中....... –

回答

12

如果你的值都是標量,那麼有一個「鍵 - 值存儲」只是一個向量沒有什麼問題。

vals <- 1:1000000 
keys <- paste0("key", 1:1000000) 
names(vals) <- keys 

可以再用

vals["key42"] 
[1] 42 

IIRC [R檢索對應於給定鍵的值使用散列基於字符的索引,因此查找要快,無論你的矢量的大小。

如果您的值可以是任意對象,那麼您確實需要一個列表。

vals <- list(1:100, lm(speed ~ dist, data=cars), function(x) x^2) 
names(vals) <- c("numbers", "model", "function") 

sq <- vals[["function"]] 
sq(5) 
[1] 25 

如果你的問題是關於構建名單,我不會太擔心。 [R內部是寫入時複製(如果他們的內容被修改的對象只被複製),這樣做就像

vals <- list(1:1000000, 1:1000000, <other big objects>) 

東西實際上不會讓一切額外的副本。

編輯:我剛剛檢查過,而且R 複製一切,如果你做lst <- list(....)。去搞清楚。所以如果你已經接近你的機器的內存限制,這是行不通的。另一方面,如果你做names(lst) <- ....,它不會作出lst的另一個副本。再次去圖。

+0

有關使用命名向量的注意事項+1。 –

+0

+1我只通過SimmonO101接受這個答案,因爲它有點複雜,但實質上兩者都是很好的答案。正如我在我的更新問題中提到的,我錯誤地認爲names()與列表不起作用,所以我試圖找到其他選項。謝謝。 –

+0

+1通過交叉校正 – embert

3

你的意思是這樣做嗎?...

xx <- 1:3 
yy <- letters[1:3] 
zz <- list(xx , yy) 
names(zz) <- c("keys" , "values") 
zz 
#$keys 
#[1] 1 2 3 

#$values 
#[1] "a" "b" "c" 

據我所知這是使向量的列表的規範方式。我很高興能夠糾正。如果你是新的R,我建議是一般不明智使用for循環,因爲有通常矢量化的方法來完成的任務,更爲高效和快捷。

+0

或多或少(不是使用這個名稱作爲名稱,而是使用了一個鍵向量;-))。我希望矢量的內容成爲列表內容的名稱。Names()是我嘗試的第一件事,我不記得爲什麼,它沒有工作(可能我做錯了什麼),並且我錯誤地認爲names()僅適用於向量。我知道關於循環的表現,這就是我要問的原因,但無論如何要感謝雙重檢查。 –

4

這裏另一個嚴重的選擇是使用data.table。使用該鍵對結構進行排序,當您擁有大量數據時,訪問元素的速度非常快。這裏的一個例子:

library(data.table) 
DT <- data.table(xx = 1:1e6, 
      k = paste0("key", 1:1e6),key="k") 

Dt是一個data.table與2列,其中我設置列k作爲一個關鍵。 DT XXķ 1:1 KEY1 2:10 key10 3:100 key100 4:1000 key1000 5:10000 key10000 ---
999996:999995 key999995 999997:999996 key999996 999998:999997 key999997 999999:999998 key999998 的1000000:999999 key999999

現在,我可以使用這樣的鍵來訪問我的data.table:

DT['key1000'] 
     k xx 
1: key1000 1000 

這裏data.table解決方案比較名爲向量標杆:

vals <- 1:1000000 
DT <- data.table(xx = vals , 
       k = paste0("key", vals),key="k") 
keys <- paste0("key", vals) 
names(vals) <- keys 
library(microbenchmark) 
microbenchmark(vals["key42"],DT["key42"],times=100) 

Unit: microseconds 
      expr  min   lq  median   uq  max neval 
vals["key42"] 111938.692 113207.4945 114924.010 130010.832 361077.210 100 
    DT["key42"] 768.753 797.0085 1055.661 1067.987 2058.985 100 
+0

+1 data.table是這些有用的軟件包之一,我一直在附近,但從來沒有時間學習它以便在生產中使用它。 –

11

它可以在一條語句來完成使用setNames

xx <- 1:3 
yy <- letters[1:3] 

要創建一個名爲列表:

或命名向量:

setNames(xx, yy) 
# a b c 
# 1 2 3 

在列表的情況下,這在程序上等同於您的「命名向量」方法,但可能稍微優雅一些​​。


下面是一些基準,顯示兩種方法一樣快。還要注意的是操作的順序是避免數據的不必要的和昂貴的拷貝非常重要:

f1 <- function(xx, yy) { 
    names(xx) <- yy 
    as.list(xx) 
} 

f2 <- function(xx, yy) { 
    out <- as.list(xx) 
    names(out) <- yy 
    out 
} 

f3 <- function(xx, yy) as.list(setNames(xx, yy)) 
f4 <- function(xx, yy) setNames(as.list(xx), yy) 

library(microbenchmark) 
microbenchmark(
    f1(xx, yy), 
    f2(xx, yy), 
    f3(xx, yy), 
    f4(xx, yy) 
) 
# Unit: microseconds 
#  expr min  lq median  uq  max neval 
# f1(xx, yy) 41.207 42.6390 43.2885 45.7340 114.853 100 
# f2(xx, yy) 39.187 40.3525 41.5330 43.7435 107.130 100 
# f3(xx, yy) 39.280 41.2900 42.1450 43.8085 109.017 100 
# f4(xx, yy) 76.278 78.1340 79.1450 80.7525 180.825 100 
+0

+1感謝setNames –

+0

也感謝基準測試 –

0

香港的輸出是錯誤的。

應該使用瓦爾斯[ 「key42」]]

> vals[["key42"]] 
[1] 42 

vals <- 1:1000000 
keys <- paste0("key", 1:1000000) 
names(vals) <- keys 

vals["key42"] 
key42 
    42 
相關問題