2017-09-16 33 views
2

假設我有以下的命名數字向量列表?轉換命名爲載體,以R中

a.list 
# $I 
# [1] 1 2 3 4 
# $II 
# [1] 5 6 7 8 

請注意,as.list(a)是不是我正在尋找。 我非常不滿意(和緩慢的大載體)的解決方案是:

names.uniq <- unique(names(a)) 
a.list <- setNames(vector('list', length(names.uniq)), names.uniq) 
for(i in 1:length(names.uniq)) { 
    names.i <- names.uniq[i] 
    a.i <- a[names(a)==names.i] 
    a.list[[names.i]] <- unname(a.i) 
} 

預先感謝您的幫助, 德文

+1

也許'split(a,names(a))'。然後'unname'列表的向量。 –

回答

6

就像我在評論說,你可以使用split創建一個列表。

a.list <- split(a, names(a)) 
a.list <- lapply(a.list, unname) 

一個班輪將是

a.list <- lapply(split(a, names(a)), unname) 
#$I 
#[1] 1 2 3 4 
# 
#$II 
#[1] 5 6 7 8 

EDIT。
然後,電郵在他的評論中發佈了一個簡化。我用德文金的方式計時,它不僅更簡單,而且快25%。

a.list <- split(unname(a),names(a)) 
+6

不需要2個lapply循環 - 'split(unname(a),names(a))'會做到這一點。 – thelatemail

1

測試瑞Barradas的解決方案VS我的上一個較大的載體

a <- 1:5e7 
    names(a) <- c(rep('I',1e7), rep('II',1e7), rep('III',1e7), rep('IV',1e7), rep('V',1e7)) 

銳的

st1 <- Sys.time() 
a.list <- split(a, names(a)) 
a.list <- lapply(a.list, unname) 
Sys.time() - st1 
Time difference of 2.560906 secs 

st1 <- Sys.time() 
names.uniq <- unique(names(a)) 
a.list <- setNames(vector('list', length(names.uniq)), names.uniq) 
for(i in 1:length(names.uniq)) { 
names.i <- names.uniq[i] 
    a.i <- a[names(a)==names.i] 
    a.list[[names.i]] <- unname(a.i) 
} 
Sys.time() - st1 
Time difference of 2.712066 secs 

thelatemail的

原來的解決方案
st1 <- Sys.time() 
    a.list <- split(unname(a),names(a)) 
Sys.time() - st1 
Time difference of 1.62851 secs 
1

我建議您查看一些擅長彙總大量數據的軟件包,例如data.table軟件包。隨着data.table,你可以這樣做:

a <- 1:5e7 
names(a) <- c(rep('I',1e7), rep('II',1e7), rep('III',1e7), 
       rep('IV',1e7), rep('V',1e7)) 

library(data.table) 
temp <- data.table(names(a), a)[, list(V2 = list(a)), V1] 
a.list <- setNames(temp[["V2"]], temp[["V1"]]) 

這裏有一些功能,以測試各種選項進行搭配:

myFun <- function(invec) { 
    x <- data.table(names(invec), invec)[, list(V2 = list(invec)), V1] 
    setNames(x[["V2"]], x[["V1"]]) 
} 

rui1 <- function(invec) { 
    a.list <- split(invec, names(invec)) 
    lapply(a.list, unname) 
} 

rui2 <- function(invec) { 
    split(unname(invec), names(invec)) 
} 

op <- function(invec) { 
    names.uniq <- unique(names(invec)) 
    a.list <- setNames(vector('list', length(names.uniq)), names.uniq) 
    for(i in 1:length(names.uniq)) { 
    names.i <- names.uniq[i] 
    a.i <- a[names(invec) == names.i] 
    a.list[[names.i]] <- unname(a.i) 
    } 
    a.list 
} 

而且微基準的10次重複的結果:

library(microbenchmark) 
microbenchmark(myFun(a), rui1(a), rui2(a), op(a), times = 10) 
# Unit: milliseconds 
#  expr  min  lq  mean median  uq  max neval 
# myFun(a) 698.1553 768.6802 932.6525 934.6666 1056.558 1168.889 10 
# rui1(a) 2967.4927 3097.6168 3199.9378 3185.1826 3319.453 3413.185 10 
# rui2(a) 2152.0307 2285.4515 2372.9896 2362.7783 2426.821 2643.033 10 
#  op(a) 2672.4703 2872.5585 2896.7779 2901.7979 2971.782 3039.663 10 

而且請注意,在測試不同的解決方案時,您可能需要考慮其他方案,例如,您期望有許多不同名稱的情況。在這種情況下,您的for循環顯着減慢。例如,用以下數據嘗試上述功能:

set.seed(1) 
b <- sample(100, 5e7, TRUE) 
names(b) <- sample(c(letters, LETTERS, 1:100), 5e7, TRUE) 
+0

哇,您使用data.table包的功能閃電般快!謝謝! –