【问题标题】:Apply a list of functions to matrix and return a matrix as a result in R将函数列表应用于矩阵并在 R 中返回矩阵作为结果
【发布时间】:2018-12-04 19:23:24
【问题描述】:

我有一个 n 列和 m 行的矩阵以及一个 f 函数列表。每个函数取一行矩阵并返回一个值,p

m 行矩阵生成 f 列的最佳方法是什么?

目前我正在这样做:

# create a random 5x5 matrix
m <- matrix(rexp(25, rate=.1), ncol=5)

# example functions, in reality more complex but with the same signature
fs <- list(function(xs) { return(mean(xs)) }, function(xs) { return(min(xs)) } )

# create a function which takes a function and applies it to each row of m
g <- function(f) { return(apply(m, 1, f)) }

# use lapply to make a call for each function in fs
# use do.call and cbind to reshape the output from a list of lists to a matrix
do.call("cbind", lapply(fs, g))

澄清编辑:上面的代码确实有效,但我想知道是否有更优雅的方法。

【问题讨论】:

  • 你的预期输出是什么?
  • 一个行数与m相同,列数与fs长度相同的矩阵,其中每个单元格是函数f在m行上的结果。
  • 请在创建随机矩阵之前使用set.seed(1234)(或任何其他数字)以重现与您相同的结果。

标签: r matrix functional-programming


【解决方案1】:

使用base R,您可以在一行中完成:

cbind(apply(m, 1, mean), apply(m, 1, min))

#          [,1]      [,2]
#[1,] 13.287748 5.2172657
#[2,]  5.855862 1.8346868
#[3,]  8.077236 0.4162899
#[4,] 10.422803 1.5899831
#[5,] 10.283001 2.0444687

这比do.call 方法快:

microbenchmark::microbenchmark(
  do.call("cbind", lapply(fs, g)),
  cbind(apply(m, 1, mean), apply(m, 1, min))
)

哪个是:

#Unit: microseconds
#                                       expr    min     lq     mean
#            do.call("cbind", lapply(fs, g)) 66.077 67.210 88.75483
# cbind(apply(m, 1, mean), apply(m, 1, min)) 57.771 58.903 67.70094
# median     uq     max neval
# 67.965 71.741 851.446   100
# 59.658 60.036 125.735   100

【讨论】:

  • 您的解决方案很好,几乎回答了这个问题,但是您不使用函数列表 fs 所以我不能接受。我需要代码灵活并获取运算符列表,而不是为每个函数编写新的应用程序。
【解决方案2】:

这就是我改编@patL 的answer 以获取函数列表的方式:

# create a random 5x5 matrix
m <- matrix(rexp(25, rate=.1), ncol=5)

# example functions, in reality more complex but with the same signature
fs <- list(function(xs) { return(mean(xs)) }, function(xs) { return(min(xs)) } )

# create a function which takes a function and applies it to each row of m
g <- function(f) { return(apply(m, 1, f)) }

# use sapply to make a call for each function in fs
# use cbind to reshape the output from a list of lists to a matrix
cbind(sapply(fs, g))

我正在使用它来为一组模型评分,例如:

# models is a list of trained models and m is a matrix of input data
g <- function(model) { return(predict(model, m)) }
# produce a matrix of model scores
cbind(sapply(models, g))

【讨论】:

    【解决方案3】:
    有数据:
    set.seed(11235813)
    
    m <- matrix(rexp(25, rate=.1), ncol=5)
    
    fs <- c("mean", "median", "sd", "max", "min", "sum")
    
    你可以做:
    sapply(fs, mapply, split(m, row(m)), USE.NAMES = T)
    
    返回:
              mean   median        sd      max       min      sum
    [1,]  9.299471 3.531394 10.436391 26.37984 1.7293010 46.49735
    [2,]  8.583419 2.904223 11.714482 28.75344 0.7925614 42.91709
    [3,]  6.292835 4.578894  6.058633 16.92280 1.8387221 31.46418
    [4,] 10.699276 5.688477 15.161685 36.91369 0.1049507 53.49638
    [5,]  9.767307 2.748114 10.767438 24.66143 1.5677153 48.83653
    

    注意:

    与上述两种方法相比,它是最慢的一种。

    【讨论】:

    • 这确实有效,但正如你所说,它很慢而且不是很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    • 2015-05-08
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2015-04-23
    • 2014-08-09
    相关资源
    最近更新 更多