1 replication
rep 函数能把输入的参数重复数次。另一个相关函数replicate 则能调用表达式数次。大多数情况下它们基本相等,只有当使用随机数时才会出现不同。现在,假定生成均匀分布随机数的runif 函数不是矢量化的,那么rep 函数每次都将重复相同的随机数,而replicate 每次的结果都不相同(由于历史的原因,其参数顺序竟然是从后到前的,这有点烦人):
rep(runif(1),5)
## [1] 0.3322252 0.3322252 0.3322252 0.3322252 0.3322252
replicate(5,runif(1))
## [1] 0.283310499 0.008578707 0.146623782 0.415137337 0.338364811
在更为复杂的例子中,replicate 会大显身手。例如,在蒙特卡罗(Monte Carlo)分析中——replicate 最主要的用途,你需要重复固定次数的分析过程且每次迭代都是相互独立的。
下一个例子将分析某人上下班时使用不同交通工具所花费的时间。这有些复杂,不过这是为了展示replicate 的作用,它非常适合于这种场景。
time_for_commute 函数用sample 随机挑选一种交通工具(小汽车、公交车或自行车),然后用rnorm 或rlnorm 找到一个正态分布或对数正态分布1 的行程时间(具体参数取决于所选的交通工具)。
time_for_commute <- function()
{
mode_of_transport <- sample(
c("car", "bus", "train", "bike"),
size = 1,
prob = c(0.1, 0.2, 0.3, 0.4)
)
time <- switch(
mode_of_transport,
car = rlnorm(1, log(30), 0.5),
bus = rlnorm(1, log(40), 0.5),
train = rnorm(1, 30, 10),
bike = rnorm(1, 60, 5)
)
names(time) <- mode_of_transport
time
}
switch 语句的存在使得这个函数很难被向量化。这意味着:为了找到上下班时间的分布,我们需要多次调用time_for_commute 来生成每天的数据。replicate 使我们能即刻进行向量化:
replicate(5,time_for_commute())
## bus bike train bus bike
## 21.79452 60.34375 29.05779 45.15100 57.18907
2 遍历列表
现在,你已经注意到向量化在R 中无处不在。事实上,你会很自然地选择编写向量化代码。因为它使代码看上去更精简,且与循环相比它的性能更好。不过,在某些情况下,保持矢量化意味着控制代码的方式不太自然。此时,apply 系列的函数能更自然地让你进行“伪矢量化”2。
最简单且常用的成员函数是lapply,它是“list apply”的缩写。lapply 的输入参数是某个函数,此函数将依次作用于列表中的每个元素上,并将结果返回到另一个列表中。
# 构建质因数分解列表:
prime_factors<-list(
two=2,
three=3,
four=c(2,2),
five=5,
six=c(2,3),
seven=7,
eight=c(2,2,2),
nine=c(3,3),
ten=c(2,5)
)
head(prime_factors)
## $two
## [1] 2
##
## $three
## [1] 3
##
## $four
## [1] 2 2
##
## $five
## [1] 5
##
## $six
## [1] 2 3
##
## $seven
## [1] 7
# 以向量化的方式在每个列表元素中搜索唯一值是很难做到的。我们可以写一个for 循环来逐个地检查元素,但这种方法有点笨拙:
unique_primes<-vector("list",length(prime_factors))
for(i in seq_along(prime_factors))
{
unique_primes[[i]]<-unique(prime_factors[[i]])
}
names(unique_primes)<-names(prime_factors)
unique_primes
## $two
## [1] 2
##
## $three
## [1] 3
##
## $four
## [1] 2
##
## $five
## [1] 5
##
## $six
## [1] 2 3
##
## $seven
## [1] 7
##
## $eight
## [1] 2
##
## $nine
## [1] 3
##
## $ten
## [1] 2 5
# lapply 大大简化了这种操作,你无需再用那些陈腔滥调的代码来进行长度和名称检查:
lapply(prime_factors,unique)
## $two
## [1] 2
##
## $three
## [1] 3
##
## $four
## [1] 2
##
## $five
## [1] 5
##
## $six
## [1] 2 3
##
## $seven
## [1] 7
##
## $eight
## [1] 2
##
## $nine
## [1] 3
##
## $ten
## [1] 2 5
# 如果函数的每次返回值大小相同,且你知其大小为多少,那么你可以使用lapply 的变种vapply。vapply 的含义是:应用于(apply)列表而返回向量(vector)。和前面一样,它的输入参数是一个列表和函数,但vapply 还需要第三个参数,即返回值的模板。它不直接返回列表,而是把结果简化为向量或数组:
vapply(prime_factors,length,numeric(1))
## two three four five six seven eight nine ten
## 1 1 2 1 2 1 3 2 2
如果输出不能匹配模板,那么vapply 将抛出一个错误——vapply 不如lapply 灵活,因为它输出的每个元素必须大小相同且必须事先就知道。
还有一种介于lapply 和vapply 之间的函数sapply,其含义为:简化(simplfy)列表应用。与其他两个函数类似,sapply 的输入参数也是一个列表和函数。它不需要模板,但它会尽可能地把结果简化到一个合适的向量和数组中。
prime_factors<-list(
two=2,
three=3,
four=c(2,2),
five=5,
six=c(2,3),
seven=7,
eight=c(2,2,2),
nine=c(3,3),
ten=c(2,5)
)
sapply(prime_factors,unique)
## $two
## [1] 2
##
## $three
## [1] 3
##
## $four
## [1] 2
##
## $five
## [1] 5
##
## $six
## [1] 2 3
##
## $seven
## [1] 7
##
## $eight
## [1] 2
##
## $nine
## [1] 3
##
## $ten
## [1] 2 5
sapply(prime_factors,length)
## two three four five six seven eight nine ten
## 1 1 2 1 2 1 3 2 2
sapply(prime_factors,summary)
## two three four five six seven eight nine ten
## Min. 2 3 2 5 2.00 7 2 3 2.00
## 1st Qu. 2 3 2 5 2.25 7 2 3 2.75
## Median 2 3 2 5 2.50 7 2 3 3.50
## Mean 2 3 2 5 2.50 7 2 3 3.50
## 3rd Qu. 2 3 2 5 2.75 7 2 3 4.25
## Max. 2 3 2 5 3.00 7 2 3 5.00
# 匿名函数传给lapply
complemented <- c(2, 3, 6, 18)
lapply(complemented,rep.int,times=4)
## [[1]]
## [1] 2 2 2 2
##
## [[2]]
## [1] 3 3 3 3
##
## [[3]]
## [1] 6 6 6 6
##
## [[4]]
## [1] 18 18 18 18
lapply(complemented,function(x) rep.int(4,time=x))
## [[1]]
## [1] 4 4
##
## [[2]]
## [1] 4 4 4
##
## [[3]]
## [1] 4 4 4 4 4 4
##
## [[4]]
## [1] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
在极个别的情况下,你可能需要循环遍历环境(而非列表)中每个变量。对此,你可以使用专门的函数eapply。当然,在最新版本的R 中,你也可以使用lapply:
env<-new.env()
env$molien<-c(1,0,1,0,1,1,2,1,3)
env$larry<-c("Really","leery","rarely","Larry")
eapply(env,length)
## $molien
## [1] 9
##
## $larry
## [1] 4
lapply(env,length)
## $molien
## [1] 9
##
## $larry
## [1] 4
rapply 是lapply 函数的递归版本,它允许你循环遍历嵌套列表。这是个特殊的要求,且如果事先使用unlist 将数据扁平化就会使代码变得更简单。
3 遍历数组
lapply 和它的小伙伴vapply 与sapply 都可用于矩阵和数组上,但它们的行为往往不是我们想要的。这三个函数把矩阵和数组看作向量,将目标函数作用于每个元素上(沿列往下移动)。而更为常见的是,当要把函数作用于一个数组时,我们希望能按行或列应用它们。下面的例子使用matlab 包,提供了对手语言所具备的功能。
library(matlab)
##
## Attaching package: 'matlab'
##
## The following object is masked from 'package:stats':
##
## reshape
##
## The following objects are masked from 'package:utils':
##
## find, fix
##
## The following object is masked from 'package:base':
##
## sum
(magic4<-magic(4))
## [,1] [,2] [,3] [,4]
## [1,] 16 2 3 13
## [2,] 5 11 10 8
## [3,] 9 7 6 12
## [4,] 4 14 15 1
magic 函数将创建一个f 方阵:n×n 的、从1 排到n2 的数字矩阵,其行数和列数相等:
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在职场中,许多言辞并非表面意思那么简单,有时需要听懂背后的“潜台词”。尤其在数据分析的领域里,掌握常用术语就像掌握一门新 ...
2025-01-04在当今信息化社会,数据分析已成为各行各业的核心驱动力。它不仅仅是对数字进行整理与计算,而是在数据的海洋中探寻规律,从而指 ...
2025-01-03又到一年年终时,各位打工人也迎来了展示成果的关键时刻 —— 年终述职。一份出色的年终述职报告,不仅能全面呈现你的工作价值, ...
2025-01-03在竞争激烈的商业世界中,竞品分析对于企业的发展至关重要。今天,我们就来详细聊聊数据分析师写竞品分析的那些事儿。 一、明确 ...
2025-01-03在数据分析的江湖里,有两个阵营总是争论不休。一派信奉“大即是美”,认为数据越多越好;另一派坚守“小而精”,力挺质量胜于规 ...
2025-01-02数据分析是一个复杂且多维度的过程,从数据收集到分析结果应用,每一步都是对信息的提炼与升华。可视化分析结果,以图表的形式展 ...
2025-01-02在当今的数字化时代,数据分析师扮演着一个至关重要的角色。他们如同现代企业的“解密专家”,通过解析数据为企业提供决策支持。 ...
2025-01-02数据分析报告至关重要 一份高质量的数据分析报告不仅能够揭示数据背后的真相,还能为企业决策者提供有价值的洞察和建议。 年薪 ...
2024-12-31数据分析,听起来好像是技术大咖的专属技能,但其实是一项人人都能学会的职场硬核能力!今天,我们来聊聊数据分析的核心流程,拆 ...
2024-12-31提到数据分析,你脑海里可能会浮现出一群“数字控”抱着电脑,在海量数据里疯狂敲代码的画面。但事实是,数据分析并没有你想象的 ...
2024-12-31关于数据分析师是否会成为失业高危职业,近年来的讨论层出不穷。在这个快速变化的时代,技术进步让人既兴奋又不安。今天,我们从 ...
2024-12-30数据分析师在现代企业中扮演着关键角色,他们的工作内容不仅丰富多样,还对企业的决策和发展起着重要的作用。正如一个经验丰富的 ...
2024-12-29数据分析师的能力要求 在当今的数据主导时代,数据分析师的角色变得尤为重要。他们不仅需要具备深厚的技术背景,还需要拥有业务 ...
2024-12-29随着技术的飞速发展与行业的持续变革,不少人心中都存有疑问:到了 2025 年,数据分析师还有前途吗?给你分享一篇阿里P8大佬最近 ...
2024-12-29如何构建数据分析整体框架? 要让数据分析发挥其最大效能,建立一个清晰、完善的整体框架至关重要。今天,就让我们一同深入探讨 ...
2024-12-27AI来了,数分人也可以很省力,今天给大家介绍7个AI+数据分析工具,建议收藏。 01酷表 EXCEL 网址:https://chatexcel.com/ 这是 ...
2024-12-26一个好的数据分析模型不仅能使分析具备条理性和逻辑性,而且还更具备结构化和体系化,并保证分析结果的有效性和准确性。好的数据 ...
2024-12-26当下,AI 的发展堪称狂飙猛进。从 ChatGPT 横空出世到各种大语言模型(LLM)接连上线,似乎每个人的朋友圈都在讨论 AI 会不会“ ...
2024-12-26数据分析师这个职业已经成为了职场中的“香饽饽”,无论是互联网公司还是传统行业,都离不开数据支持。想成为一名优秀的数据分析 ...
2024-12-26在数据驱动决策成为商业常态的今天,数据分析师这一职业正迎来前所未有的机遇与挑战。很多希望转行或初入职场的人士不禁询问:数 ...
2024-12-25