
R語言數(shù)據(jù)處理篇之高級循環(huán)
1 replication
rep 函數(shù)能把輸入的參數(shù)重復數(shù)次。另一個相關函數(shù)replicate 則能調用表達式數(shù)次。大多數(shù)情況下它們基本相等,只有當使用隨機數(shù)時才會出現(xiàn)不同。現(xiàn)在,假定生成均勻分布隨機數(shù)的runif 函數(shù)不是矢量化的,那么rep 函數(shù)每次都將重復相同的隨機數(shù),而replicate 每次的結果都不相同(由于歷史的原因,其參數(shù)順序竟然是從后到前的,這有點煩人):
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 最主要的用途,你需要重復固定次數(shù)的分析過程且每次迭代都是相互獨立的。
下一個例子將分析某人上下班時使用不同交通工具所花費的時間。這有些復雜,不過這是為了展示replicate 的作用,它非常適合于這種場景。
time_for_commute 函數(shù)用sample 隨機挑選一種交通工具(小汽車、公交車或自行車),然后用rnorm 或rlnorm 找到一個正態(tài)分布或對數(shù)正態(tài)分布1 的行程時間(具體參數(shù)取決于所選的交通工具)。
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 語句的存在使得這個函數(shù)很難被向量化。這意味著:為了找到上下班時間的分布,我們需要多次調用time_for_commute 來生成每天的數(shù)據(jù)。replicate 使我們能即刻進行向量化:
replicate(5,time_for_commute())
## bus bike train bus bike
## 21.79452 60.34375 29.05779 45.15100 57.18907
2 遍歷列表
現(xiàn)在,你已經(jīng)注意到向量化在R 中無處不在。事實上,你會很自然地選擇編寫向量化代碼。因為它使代碼看上去更精簡,且與循環(huán)相比它的性能更好。不過,在某些情況下,保持矢量化意味著控制代碼的方式不太自然。此時,apply 系列的函數(shù)能更自然地讓你進行“偽矢量化”2。
最簡單且常用的成員函數(shù)是lapply,它是“l(fā)ist apply”的縮寫。lapply 的輸入?yún)?shù)是某個函數(shù),此函數(shù)將依次作用于列表中的每個元素上,并將結果返回到另一個列表中。
# 構建質因數(shù)分解列表:
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 循環(huán)來逐個地檢查元素,但這種方法有點笨拙:
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
# 如果函數(shù)的每次返回值大小相同,且你知其大小為多少,那么你可以使用lapply 的變種vapply。vapply 的含義是:應用于(apply)列表而返回向量(vector)。和前面一樣,它的輸入?yún)?shù)是一個列表和函數(shù),但vapply 還需要第三個參數(shù),即返回值的模板。它不直接返回列表,而是把結果簡化為向量或數(shù)組:
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 之間的函數(shù)sapply,其含義為:簡化(simplfy)列表應用。與其他兩個函數(shù)類似,sapply 的輸入?yún)?shù)也是一個列表和函數(shù)。它不需要模板,但它會盡可能地把結果簡化到一個合適的向量和數(shù)組中。
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
# 匿名函數(shù)傳給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
在極個別的情況下,你可能需要循環(huán)遍歷環(huán)境(而非列表)中每個變量。對此,你可以使用專門的函數(shù)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 函數(shù)的遞歸版本,它允許你循環(huán)遍歷嵌套列表。這是個特殊的要求,且如果事先使用unlist 將數(shù)據(jù)扁平化就會使代碼變得更簡單。
3 遍歷數(shù)組
lapply 和它的小伙伴vapply 與sapply 都可用于矩陣和數(shù)組上,但它們的行為往往不是我們想要的。這三個函數(shù)把矩陣和數(shù)組看作向量,將目標函數(shù)作用于每個元素上(沿列往下移動)。而更為常見的是,當要把函數(shù)作用于一個數(shù)組時,我們希望能按行或列應用它們。下面的例子使用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 函數(shù)將創(chuàng)建一個f 方陣:n×n 的、從1 排到n2 的數(shù)字矩陣,其行數(shù)和列數(shù)相等:
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉換:從基礎用法到實戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關聯(lián)查詢效率:打破 “拆分必慢” 的認知誤區(qū) 在 MySQL 數(shù)據(jù)庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結構數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結構數(shù)據(jù)(如數(shù)據(jù)庫表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預期算子的內涵、作用與應用解析 動態(tài)隨機一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結構數(shù)據(jù)特征價值的專業(yè)核心 表結構數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲的結構化數(shù)據(jù),如數(shù)據(jù)庫表、Excel 表、 ...
2025-09-17Excel 導入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實戰(zhàn)應用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時,“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗與 t 檢驗:差異、適用場景與實踐應用 在數(shù)據(jù)分析與統(tǒng)計學領域,假設檢驗是驗證研究假設、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結構數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結構數(shù)據(jù)(以 “行 - 列” 存儲的結構化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計劃中 rows 數(shù)量的準確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調優(yōu)中,EXPLAIN執(zhí)行計劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對象的 text 與 content:區(qū)別、場景與實踐指南 在 Python 進行 HTTP 網(wǎng)絡請求開發(fā)時(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結構數(shù)據(jù)價值的核心操盤手 表格結構數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫表)是企業(yè)最基礎、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請求工具對比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請求(如接口調用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長浮點數(shù)據(jù)的科學計數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長浮點數(shù)據(jù)時的科學計數(shù)法問題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務數(shù)據(jù)分析步驟的落地者與價值優(yōu)化者 業(yè)務數(shù)據(jù)分析是企業(yè)解決日常運營問題、提升執(zhí)行效率的核心手段,其價值 ...
2025-09-12用 SQL 驗證業(yè)務邏輯:從規(guī)則拆解到數(shù)據(jù)把關的實戰(zhàn)指南 在業(yè)務系統(tǒng)落地過程中,“業(yè)務邏輯” 是連接 “需求設計” 與 “用戶體驗 ...
2025-09-11塔吉特百貨孕婦營銷案例:數(shù)據(jù)驅動下的精準零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當下,精準營銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務數(shù)據(jù)分析:概念辨析與協(xié)同價值 在數(shù)據(jù)驅動決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類分析:從操作實踐到業(yè)務價值挖掘 在數(shù)據(jù)分析場景中,聚類分析作為 “無監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價值導向 統(tǒng)計模型作為數(shù)據(jù)分析的核心工具,并非簡單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10