2017-09-16 49 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包的功能闪电般快!谢谢! –