【问题标题】:dictionary and list comprehension in RR中的字典和列表理解
【发布时间】:2016-11-18 23:02:41
【问题描述】:

有什么通用的方法可以更快地完成以下 R 代码吗?例如,在 python dict 理解中(参见下面的等效项)将是一个不错的更快的选择。

R:

l1 <- 1:3
l2 <- c("a", "b", "c")
foo <- function(x) {return(5*x)}
bar <- list()
for (i in 1:length(l1)) bar[l2[i]] <- foo(l1[i])

Python

l1 = range(1, 4)
l2 = ["a", "b", "c"]
def foo(x):
    return 5*x
{b: foo(a) for a, b in zip(l1, l2)}

【问题讨论】:

  • setNames(lapply(l1,foo),l2).
  • 如果你不需要它作为一个列表(因为每个元素只有一个数字),你可以使用sapply而不是lapply
  • 由于乘法(因此foo)是矢量化的,你可以只做as.list(setNames(l1 * 5, l2))as.list(setNames(foo(l1), l2));删除 as.list 以将其保留为命名的数字向量。
  • 感谢您的所有回答。

标签: r list list-comprehension dictionary-comprehension


【解决方案1】:

我们谈论的是速度,所以让我们做一些基准测试:

library(microbenchmark)
microbenchmark(op = {for (i in 1:length(l1)) bar[l2[i]] <- foo(l1[i])},
               lapply = setNames(lapply(l1,foo),l2),
               vectorised = setNames(as.list(foo(l1)), l2))

Unit: microseconds
       expr   min    lq     mean median     uq    max neval
         op 7.982 9.122 10.81052  9.693 10.548 36.206   100
     lapply 5.987 6.557  7.73159  6.842  7.270 55.877   100
 vectorised 4.561 5.132  6.72526  5.417  5.987 80.964   100

但是这些小值并没有多大意义,所以我将向量长度提高到 10,000,你会真正看到差异:

l <- 10000
l1 <- seq_len(l)
l2 <- sample(letters, l, replace = TRUE)

microbenchmark(op = {bar <- list(); for (i in 1:length(l1)) bar[l2[i]] <- foo(l1[i])},
               lapply = setNames(lapply(l1,foo),l2),
               vectorised = setNames(as.list(foo(l1)), l2),
               times = 100)

Unit: microseconds
       expr       min        lq       mean     median        uq       max neval
         op 30122.865 33325.788 34914.8339 34769.8825 36721.428 41515.405   100
     lapply 13526.397 14446.078 15217.5309 14829.2320 15351.933 19241.767   100
 vectorised   199.559   259.997   349.0544   296.9155   368.614  3189.523   100

但是根据其他人所说的,它不必是一个列表。如果您删除列表要求:

microbenchmark(setNames(foo(l1), l2))

Unit: microseconds
                  expr    min      lq     mean  median     uq      max neval
 setNames(foo(l1), l2) 22.522 23.8045 58.06888 25.0875 48.322 1427.417   100

【讨论】:

    猜你喜欢
    • 2021-03-12
    • 1970-01-01
    • 2016-11-09
    • 2011-03-14
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多