百日筑基篇——future.apply包介绍(R语言初识四)
前言
鄙人对计算机编程语言有较多兴趣,故学R语言,作为一个萌新,希望以这种方式,对自己的学习不断进行复盘,同时希望多多指教!!
一、future.apply是什么?
future.apply R包是R语言中的一个扩展包,它提供了一种简单的方法来并行处理数据集。
该包基于R的future框架,将函数应用于数据集的每个元素,并自动分发任务到多个处理器上进行并行计算。
这样可以加快计算速度,尤其适用于较大的数据集和计算密集型任务。
二、包中函数介绍
future.apply包提供了一系列的函数,与R的apply家族函数类似,包括future_map()、future_apply()、future_lapply()、future_sapply()等。
这些函数允许用户在数据集的每个元素上应用自定义的函数,并通过将计算任务分发到多个处理器来实现并行计算。
与传统的apply函数相比,future.apply在处理大型数据集时可以显著提高计算效率。
1. future_apply()
通过Future对数据框或矩阵等的行列应用此函数
不管future使用什么后端。它返回一个向量、数组或通过将函数应用于数组或矩阵的行列而获得的列表值。
代码如下(示例):
#加载包
library(future)
library(future.apply)
#创建矩阵
X <- matrix(c(1:4, 1, 6:8), nrow = 2L)
Y0 <- apply(X, MARGIN = 1L, FUN = table)
Y1 <- future_apply(X, MARGIN = 1L, FUN = table)
# 检测Y0 与Y1 返回结果是否相同
stopifnot(all.equal(Y1, Y0, check.attributes = FALSE))
#并行后端使用
plan(multisession)
set.seed(0xBEEF)
Y1 <- future_apply(X, MARGIN = 1L, FUN = sample, future.seed = TRUE)
print(Y1)
#指定代码按顺序执行,不进行并行计算。
plan(sequential)
set.seed(0xBEEF)
Y2 <- future_apply(X, MARGIN = 1L, FUN = sample, future.seed = TRUE)
print(Y2)
#返回结果一致,使用并行计算和顺序计算只是速率的快慢
stopifnot(all.equal(Y1, Y2))
2. 分组操作函数
future_by(data, INDICES, FUN, …, .progress = “none”)
future_tapply(X, INDEX, FUN, …, .progress = “none”)
根据指定的因子对数据集或向量进行分组,并在每个组上应用指定的函数
future_by()函数可以处理数据集的多个列,然后在每个组上应用函数。而future_tapply()函数则主要针对单个向量,将其按照因子分组
代码如下(示例):
library(datasets)
library(stats)
#对datasets 包中的一个内置数据集操作
plan(multisession)
y1 <- future_by(warpbreaks, warpbreaks[,"tension"],
function(x) lm(breaks ~ wool, data = x))
Y1 <- future_tapply(warpbreaks$breaks,warpbreaks[,"tension"],sum)
plan(sequential)
y2 <- future_by(warpbreaks, warpbreaks[,"tension"],
function(x) lm(breaks ~ wool, data = x))
3. 对数据集每个元素应用函数的方法
future_lapply() :对列表或向量中的每个元素应用函数,并将每次应用的结果存储在一个新的列表中,最后返回这个列表。
future_sapply() :在功能上类似于future_lapply函数,但它会尝试将结果简化为更简单的对象,如向量或矩阵。
future_vapply() :与future_sapply函数类似,但要求指定结果的精确类型,以提高代码的稳定性和可读性
future_mapply() :可以用于对多个数据集(列表或向量)进行相同的函数操作。将函数应用于多个数据集的对应元素。每个数据集中的元素必须具有相同的长度
代码如下(示例):
#创建列表
x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE, FALSE, FALSE, TRUE))
plan(multisession)
y1 <- future_lapply(x, FUN = quantile, probs = 1:3/4)
y0 <- future_sapply(x, FUN = quantile,probs = 1:3/4)
stopifnot(all.equal(y1, y0)) #会报错,y1是列表,y0是向量
y2 <- future_vapply(x, FUN = quantile, FUN.VALUE = double(5L)) #指定返回结果的数据类型为double(双精度浮点数),且长度为5
# 创建两个向量
x <- c(1, 2, 3)
y <- c(4, 5, 6)
y3 <- future_mapply(function(x,y) {x+y} , x,y)
4. future_eapply()
函数利用并行计算框架在一个环境中并行地应用函数。
future_eapply()函数中的任务是相互独立的,它们之间没有依赖关系。
env表示一个环境对象,用于存储函数和参数。
my_env <- new.env() #使用new.env()创建了一个空的环境对象my_env
my_env$fun1 <- function(x) {x ^ 2}
my_env$fun2 <- function(x) {sin(x)}
my_env$param1 <- 1:10
my_env$param2 <- pi/4
# 使用future_eapply()函数并行执行函数
library(future)
library(future.apply)
plan(multisession)
my_parallel_function <- function(env, fun_name, param_name) {
fun <- env[[fun_name]]
param <- env[[param_name]]
result <- future_lapply(param, function(x) {
fun(x)
})
return(result)
}
res1 <- my_parallel_function(my_env, "fun1", "param1")
res2 <- my_parallel_function(my_env, "fun2", "param2")
总结
如果您对apply系列函数有一定了解,那对于future.apply包的掌握就很容易;只要理解并行计算与串行计算的区别就行。
能阻止你的追梦,只有你自己能放弃你的梦想。
–2023-7-6 筑基篇