Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将命名向量转换为R中的列表_R_Vector - Fatal编程技术网

将命名向量转换为R中的列表

将命名向量转换为R中的列表,r,vector,R,Vector,假设我有以下命名的数值向量: a <- 1:8 names(a) <- rep(c('I', 'II'), each = 4) 注意,as.lista不是我想要的。 对于大向量,我的解决方案非常不令人满意且速度缓慢: names.uniq <- unique(names(a)) a.list <- setNames(vector('list', length(names.uniq)), names.uniq) for(i in 1:length(names.uniq))

假设我有以下命名的数值向量:

a <- 1:8
names(a) <- rep(c('I', 'II'), each = 4)
注意,as.lista不是我想要的。 对于大向量,我的解决方案非常不令人满意且速度缓慢:

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)
}
提前感谢您的帮助,
Devin

正如我在评论中所说,您可以使用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
编辑。 然后,最近的一封邮件在他的评论中对此进行了简化。我用德文·金的方法计时,不仅简单,而且速度快了25%

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

在更大的向量上测试Rui Barradas的解决方案与我的原始解决方案

  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(unname(a),names(a))
Sys.time() - st1
Time difference of 1.62851 secs

我建议查看那些擅长聚合大量数据的包,比如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"]])

还注意,在测试不同的解决方案时,您可能需要考虑其他场景,例如,您希望有很多不同名称的情况。在这种情况下,for循环会显著减慢。例如,使用以下数据尝试上述函数:

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

要同时处理未命名向量,请使用以下命令:

vec_to_list <- function(vec) {
  if (is.null(names(vec))) names(vec) <- 1:length(vec)
  split(unname(vec), names(vec))
}

也许是斯普利塔,纳萨。然后取消对列表向量的命名。不需要两个lappy循环-splitunnamea,namesa就可以了。哇,你使用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
}
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
set.seed(1)
b <- sample(100, 5e7, TRUE)
names(b) <- sample(c(letters, LETTERS, 1:100), 5e7, TRUE)
vec_to_list <- function(vec) {
  if (is.null(names(vec))) names(vec) <- 1:length(vec)
  split(unname(vec), names(vec))
}