如何从两个向量中创建R中的列表(一个是键,另一个是值)?

Pab*_*cia 24 r

我有两个向量,我想在R中创建一个列表,其中一个向量是键,另一个是值.我以为我会在我的书中轻松找到答案或googleing并且我期待找到一个解决方案,比如在向量中添加名称(名称(v)< - names_vector),但我失败了.

我有两种可能的解决方案,但对我来说似乎都不优雅.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]}
Run Code Online (Sandbox Code Playgroud)

我的解决方案2:通过命名向量的间接路径:

    > names(xx) <- letters[1:3]
    > as.list(xx)
Run Code Online (Sandbox Code Playgroud)

似乎我有一个解决方案,但我的矢量有100万或更多的元素,我不仅担心编码风格(对我很重要)而且还担心效率(但我不知道如何在R中进行分析).有没有更合适的方法呢?使用指定的矢量快捷方式是一个好习惯吗?

[[更新]]我的applogies,可能我过于简化了问题,使其可重现.我想给列表的元素命名.我首先尝试了names(),但似乎我做错了什么并且没有用.所以我错误地认为names()不适用于列表.但他们确实如接受的答案所示

Hon*_*Ooi 17

如果你的值都是标量,那么拥有一个只是一个向量的"键值存储"就没有错.

vals <- 1:1000000
keys <- paste0("key", 1:1000000)
names(vals) <- keys
Run Code Online (Sandbox Code Playgroud)

然后,您可以检索与给定键对应的值

vals["key42"]
[1] 42
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果你的问题是关于构建列表,我不会太担心.R内部是写时复制(只有在修改了内容时才复制对象),所以做了类似的事情

vals <- list(1:1000000, 1:1000000, <other big objects>)
Run Code Online (Sandbox Code Playgroud)

实际上不会制作一切的额外副本.

编辑:我刚检查过,如果你这样做,R 复制一切lst <- list(....).去搞清楚.因此,如果您已经接近计算机的内存限制,则无法使用.另一方面,如果你这样做names(lst) <- ....,它将不再制作另一份副本lst.再来一次.


flo*_*del 14

它可以在一个语句中使用setNames:

xx <- 1:3
yy <- letters[1:3]
Run Code Online (Sandbox Code Playgroud)

要创建命名列表:

as.list(setNames(xx, yy))
# $a
# [1] 1
# 
# $b
# [1] 2
# 
# $c
# [1] 3
Run Code Online (Sandbox Code Playgroud)

或者命名向量:

setNames(xx, yy)
# a b c 
# 1 2 3
Run Code Online (Sandbox Code Playgroud)

在列表的情况下,这在程序上等同于您的"命名向量"方法,但可能更优雅.


以下是一些基准测试,表明这两种方法同样快.另请注意,操作顺序对于避免不必要且昂贵的数据副本非常重要:

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
Run Code Online (Sandbox Code Playgroud)


ags*_*udy 5

这里的另一个严肃的选择是使用data.table。使用键对结构进行排序,特别是在有大量元素的情况下,访问元素的速度非常快。这里是一个例子:

library(data.table)   
DT <- data.table(xx = 1:1e6, 
             k = paste0("key", 1:1e6),key="k")
Run Code Online (Sandbox Code Playgroud)

Dt是具有2列的data.table,其中我将k列设置为键。DT xx k 1:1键1 2:10键10 3:100键100 4:1000键1000 5:10000键10000 ---
999996:999995 key999995 999997:999996 key999996 999998:999997 key999997 999999:999998 key999998 1000000:999999 key999999

现在,我可以使用如下键访问data.table:

DT['key1000']
         k   xx
1: key1000 1000
Run Code Online (Sandbox Code Playgroud)

这里是将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
Run Code Online (Sandbox Code Playgroud)