R語言系列3:高級(jí)數(shù)據(jù)管理
此文內(nèi)容為《R語言實(shí)戰(zhàn)》的筆記瞬铸,人民郵電出版社出版。
從高中電腦課學(xué)VB開始,大一課內(nèi)開始學(xué)習(xí)C++憨颠,到后來大二為了數(shù)模學(xué)習(xí)Matlab,到大三為了搞深度學(xué)習(xí)自學(xué)Python积锅,到研究生之初學(xué)習(xí)Stata——選擇一門語言對(duì)我來說就像是小時(shí)候玩冒險(xiǎn)島爽彤,到10級(jí)的時(shí)候是轉(zhuǎn)戰(zhàn)士好還是弓箭手好一般的糾結(jié)。我查閱了很多B乎的文章缚陷,最后覺得可能R比較合適現(xiàn)在的我适篙。
作為從Python轉(zhuǎn)進(jìn)來R的新手,我把可能會(huì)用經(jīng)常需要用到或經(jīng)常需要查閱的代碼貼上來蹬跃,主要是為了日后方便查找匙瘪,就像“字典”一樣。推文的順序與教材不同蝶缀,為了簡(jiǎn)潔丹喻,我還會(huì)刪除一些我個(gè)人認(rèn)為不太重要的章節(jié)。我還會(huì)按照自己的學(xué)習(xí)進(jìn)度發(fā)布文章翁都,請(qǐng)讀者見諒碍论。
本文章僅供學(xué)習(xí)參考,請(qǐng)勿轉(zhuǎn)載柄慰,侵刪鳍悠!
目錄
-
5 高級(jí)數(shù)據(jù)管理
-
5.2 數(shù)值和字符串處理函數(shù)
- 5.2.1 數(shù)學(xué)函數(shù)
- 5.2.2 統(tǒng)計(jì)函數(shù)
- 5.2.3 概率函數(shù)
- 5.2.4 字符處理函數(shù)
- 5.2.5 其他實(shí)用函數(shù)
-
5.4 控制流
- 5.4.1 循環(huán)結(jié)構(gòu)
- 5.4.2 判斷結(jié)構(gòu)
- 5.4.3 用戶自定義函數(shù)
-
5.6 整合與重構(gòu)
- 5.6.1 數(shù)據(jù)集的轉(zhuǎn)置
- 5.6.2 整合數(shù)據(jù)
- 5.6.3 reshape2包
-
5.2 數(shù)值和字符串處理函數(shù)
第5章 高級(jí)數(shù)據(jù)管理
在第4章税娜,我們學(xué)習(xí)了R中基本的數(shù)據(jù)處理方法。在第5章藏研,我們主要瀏覽R中的多種數(shù)學(xué)敬矩、統(tǒng)計(jì)和字符處理函數(shù),了解如何自己編寫函數(shù)來實(shí)現(xiàn)數(shù)據(jù)處理和分析任務(wù)蠢挡,并了解數(shù)據(jù)的整合和概述方法以及數(shù)據(jù)集的重塑和重構(gòu)弧岳。
5.2 數(shù)值和字符處理函數(shù)
R中作為數(shù)據(jù)處理基石的函數(shù),可以分為數(shù)值函數(shù)(數(shù)學(xué)业踏、統(tǒng)計(jì)禽炬、概率)和字符串處理函數(shù)。
5.2.1 數(shù)學(xué)函數(shù)
R中常用的數(shù)學(xué)函數(shù)有:
== 函數(shù) == == 描述 ==
abs(x) 絕對(duì)值
sqrt(x) 平方根
ceiling(x) 不小于x的最小整數(shù)
floor(x) 不大于x的最大整數(shù)
trunc(x) 向0方向取整
round(x, digits=n) 將x舍入為指定小數(shù)位數(shù)
signif(x, digits=n) 將x舍入為指定的有效數(shù)字位數(shù)
cos(x),sin(x),tan(x) 三角函數(shù)
acos(x),asin(x),... 反三角函數(shù)
cosh(x),sinh(x),... 雙曲三角函數(shù)
acosh(x),... 反雙曲三角函數(shù)
log(x, base=n) 對(duì)x取n為底數(shù)的對(duì)數(shù)
log(x) 自然對(duì)數(shù)
log10(x) 常用對(duì)數(shù)
exp(x) 自然指數(shù)
對(duì)數(shù)據(jù)做變換是這些函數(shù)的主要用途勤家。這些函數(shù)作用于vector或matrix或data.frame對(duì)象會(huì)作用于每一個(gè)獨(dú)立的值腹尖,見:
V1 = c(1:10)
V2 = c(11:20)
M = matrix(V1, nrow = 2)
D = data.frame(V1, V2)
sqrt(V1)
## [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
## [9] 3.000000 3.162278
sqrt(M)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1.000000 1.732051 2.236068 2.645751 3.000000
## [2,] 1.414214 2.000000 2.449490 2.828427 3.162278
sqrt(D)
## V1 V2
## 1 1.000000 3.316625
## 2 1.414214 3.464102
## 3 1.732051 3.605551
## 4 2.000000 3.741657
## 5 2.236068 3.872983
## 6 2.449490 4.000000
## 7 2.645751 4.123106
## 8 2.828427 4.242641
## 9 3.000000 4.358899
## 10 3.162278 4.472136
5.2.2 統(tǒng)計(jì)函數(shù)
常用的統(tǒng)計(jì)函數(shù)如表所示:
== 函數(shù) == == 描述 ==
mean(x) 平均值
median(x) 中位數(shù)
sd(x) 樣本標(biāo)準(zhǔn)差 (用n-1)
var(x) 樣本方差 (用n-1)
mad(x) 絕對(duì)中位數(shù)
quantile(x, probs) 求分位數(shù)
range(x) 求值域
sum(x) 求和
diff(x, lag=n) n階差分
min(x) 最小值
max(x) 最大值
scale(x, 數(shù)據(jù)中心化(center=TRUE)
cener=TRUE, 數(shù)據(jù)標(biāo)準(zhǔn)化(center和scale=TRUE)
scale=TRUE)
上面的函數(shù)一般會(huì)有na.rm
選項(xiàng),當(dāng)na.rm=TRUE
時(shí)會(huì)排除缺失值進(jìn)行計(jì)算伐脖。具體請(qǐng)參考help(·)
热幔。
一個(gè)具體的應(yīng)用是:
x <- c(1:8)
mean(x)
## [1] 4.5
sd(x)
## [1] 2.44949
如果冗余地寫,那么有:
x <- c(1:8)
n <- length(x)
meanx <- sum(x)/n
css <- sum((x-meanx)^2)
sdx <- sqrt(css/(n-1))
meanx
## [1] 4.5
sdx
## [1] 2.44949
5.2.3 概率函數(shù)
概率函數(shù)通常用來生成特征已知的模擬數(shù)據(jù)讼庇,以及在用于編寫的統(tǒng)計(jì)函數(shù)中計(jì)算概率值断凶。
在R中,概率函數(shù)形如:
[dpqr]分布名縮寫()
其中:
- d = 概率密度函數(shù)(pdf, density的d)
- p = 累積分布函數(shù)(cdf, 給定分位點(diǎn)求概率p(X<=x)的p)
- q = 分位數(shù)函數(shù)(quantile function的q巫俺,給定概率p求分位數(shù)數(shù),是p的反函數(shù))
- r = 生成隨機(jī)數(shù)(random)
例如:
x <- pretty(c(-3,3), 50)
pdf <- dnorm(x) # 概率密度函數(shù)
cdf <- pnorm(x) # 累積分布函數(shù)
quan <- qnorm( pretty(c(0,1), 100) ) # 分位數(shù)函數(shù)
layout(matrix(c(1,2,3,3), 2, 2))
plot(x, pdf, title("dnorm"))
plot(x, cdf, title("pnorm"))
plot(pretty(c(0,1), 100), quan, title("qnorm"))
另外:
# 位于 z=1.96 左側(cè)的標(biāo)準(zhǔn)正態(tài)分布pdf下方的面積是多少(知道分位點(diǎn)求概率)
pnorm(1.96)
## [1] 0.9750021
# 標(biāo)準(zhǔn)正態(tài)分布的0.9分位點(diǎn)值為多少(知道概率求分位點(diǎn))
qnorm(0.9750021)
## [1] 1.96
關(guān)于畫圖的命令會(huì)在下一篇推文介紹肿男。
1.關(guān)于設(shè)定隨機(jī)種子
每次生成為隨機(jī)數(shù)的時(shí)候介汹,函數(shù)都會(huì)使用一個(gè)不同的種子,因此也會(huì)產(chǎn)生不同的結(jié)果舶沛。你可以通過set.seed()
指定某個(gè)種子嘹承,讓隨機(jī)的結(jié)果可以重現(xiàn)(reproducible),見:
runif(5)
## [1] 0.9580880 0.9346797 0.5693708 0.6829771 0.6390400
runif(5)
## [1] 0.2776539 0.6784761 0.8737694 0.8826680 0.9218422
set.seed(1234)
runif(5)
## [1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
set.seed(1234)
runif(5)
## [1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
2.多元正態(tài)數(shù)據(jù)
在模擬研究和蒙特卡洛方法中如庭,你經(jīng)常需要獲取來自給定均值向量和協(xié)方差的多元正態(tài)分布的數(shù)據(jù)叹卷。
MASS包中的mvrnorm()
可以讓這個(gè)問題變得容易,請(qǐng)先安裝MASS包:
install.packages("MASS")
然后可以使用:
library(MASS)
## Warning: package 'MASS' was built under R version 4.0.2
options(digits = 3)
set.seed(1234)
mean <- c(230.7, 145.7, 3.6)
sigma <- matrix(c(15360.8, 6721.2, -47.1,
6721.2, 4700.9, -16.5,
-47.1, -16.5, .3),
nrow = 3, ncol = 3)
mydata <- mvrnorm(10, mean, sigma)
mydata <- as.data.frame(mydata)
names(mydata) <- c("Y", "X1", "X2")
mydata
## Y X1 X2
## 1 74.5 90.43 4.16
## 2 248.2 196.43 3.46
## 3 351.0 236.71 3.15
## 4 -56.3 4.26 4.62
## 5 299.3 138.24 3.04
## 6 291.0 179.52 2.88
## 7 151.6 129.12 4.10
## 8 148.4 144.53 3.54
## 9 147.5 140.93 3.92
## 10 161.4 9.96 3.21
5.2.4 字符處理函數(shù)
數(shù)學(xué)和統(tǒng)計(jì)函數(shù)是用來處理數(shù)值型數(shù)據(jù)的坪它,而字符處理函數(shù)可以從文本中抽取需要的數(shù)據(jù)信息骤竹。常見的字符串處理函數(shù)有:
== 函數(shù) == == 描述 ==
nchar(x) 計(jì)算x中的字符數(shù)量
substr(x,start,end) 提取或替換字符串中的子串
grep(pattern,x) 在x中搜索某種模式
sub(pattern, 把x中pattern替換為replacement
replacement,
x)
strsplit(x, split) 在split處分割向量x的元素
paste(...,sep="") 連接字符串,分隔符為sep
toupper(x) 大寫轉(zhuǎn)換
tolower(x) 小寫轉(zhuǎn)換
具體的函數(shù)形式請(qǐng)參考help文檔往毡。
5.2.5 其他實(shí)用函數(shù)
== 函數(shù) == == 描述 ==
length(x) 對(duì)象x的長(zhǎng)度
seq(from,to,by) 生成從from到to間隔為by的序列
rep(x,n) 重復(fù)x序列n次
cut(x,n) 將連續(xù)型變量x分割為有n個(gè)水平的因子
pretty(x,n) 將連續(xù)變量x均勻劃分為n個(gè)區(qū)間
cat(..., 連接...中的對(duì)象蒙揣,并輸出到屏幕或file中
file="myfile",
append=FALSE)
使用上面的函數(shù)時(shí),請(qǐng)先查看help獲取詳細(xì)信息开瞭。
另外懒震,字符串里面該可以使用以下轉(zhuǎn)義字符:
== 字符 == == 描述 ==
\n 換行符(回車)
\t 制表符(tab)
\' 單引號(hào)
\b 退格
可以在Console輸入 ?Quotes 了解更多
例如:
name <- "Bob"
cat("Hello", name, "\b.\n", "Isn\'t R", "\t", "GREAT?\n")
## Hello Bob .
## Isn't R GREAT?
在這里罩息,使用\b
是因?yàn)?code>cat在連接對(duì)象時(shí),每個(gè)對(duì)象都會(huì)用空格分開个扰。句號(hào)和最后一個(gè)單詞之間不需要空格瓷炮,所以先用\b
再輸入.
消除不要的空格。
5.4 控制流
在這里介紹控制流递宅,即判斷和循環(huán)結(jié)構(gòu)娘香。
5.4.1 循環(huán)結(jié)構(gòu)
1. for循環(huán)
用for循環(huán)重復(fù)執(zhí)行語句,知道某個(gè)變量的值不在包含在序列seq中為止恐锣,語法是:
for (var in seq) {statement}
例如:
for (i in 1:3) {print("Hello world!")}
## [1] "Hello world!"
## [1] "Hello world!"
## [1] "Hello world!"
2. while循環(huán)
while循環(huán)地重復(fù)執(zhí)行一條語句茅主,知道條件不為真為止,語法是:
while (cond) {statement}
例如:
i <- 3
while (i>0) {print("Hello world"); i <- i-1}
## [1] "Hello world"
## [1] "Hello world"
## [1] "Hello world"
5.4.2 判斷結(jié)構(gòu)
1. if-else 結(jié)構(gòu)
語法為:
if (cond) {statement}
if (cond) {statement1} else {statement2}
2. ifelse 結(jié)構(gòu)
語法是:
ifelse(cond, statement1, statement2)
如果cond
為真土榴,那么執(zhí)行statement1诀姚,否則執(zhí)行statement2。例如:
ifelse(1>2, {"1更大"}, {"2更大"})
## [1] "2更大"
如果程序的行為是二元的玷禽,或者希望input和output均為向量時(shí)赫段,盡量使用ifelse
結(jié)構(gòu)
3. switch結(jié)構(gòu)
語法是:
switch(expr, ...)
其中,...
表示與expr
的各種輸出值綁定的語句矢赁∨大希看下面的代碼就一目了然了:
fellings <- c("sad", "afraid")
for (i in fellings){
print(
switch (i,
happy = "I am glad you are happy!",
afraid = "There is nothing to fear.",
sad = "Cheer up!",
angry = "Calm down now."
)
)
}
## [1] "Cheer up!"
## [1] "There is nothing to fear."
5.4.3 用戶自編函數(shù)
R最大的優(yōu)點(diǎn)之一就是用戶可以自行添加函數(shù)。一個(gè)函數(shù)的基本結(jié)構(gòu)的語法是:
myfunction <- function(arg1, arg2, ...){
statements
return(object)
}
函數(shù)的對(duì)象只能在內(nèi)部使用撩银,返回的對(duì)象的數(shù)據(jù)類型是任意的给涕,從標(biāo)量到列表都可以。比如:
judge <- function(num1, num2){
return(ifelse(num1>num2, num1, num2))
}
judge(4,100)
## [1] 100
5.6 整合與重構(gòu)
R提供了很多方法用來整合(aggregate)和重構(gòu)(reshape)數(shù)據(jù)额获。后面將使用在R基本安裝中的mtcars
數(shù)據(jù)框:
mtcars[1:3,1:3]
## mpg cyl disp
## Mazda RX4 21.0 6 160
## Mazda RX4 Wag 21.0 6 160
## Datsun 710 22.8 4 108
5.6.1 數(shù)據(jù)集的轉(zhuǎn)置
轉(zhuǎn)置即反轉(zhuǎn)行和列够庙,直接使用t()
就可以直接對(duì)一個(gè)矩陣或一個(gè)數(shù)據(jù)框進(jìn)行轉(zhuǎn)置了。對(duì)于數(shù)據(jù)框抄邀,行名將變成列名耘眨。如果是對(duì)向量進(jìn)行t()
函數(shù),那么第一次t()
會(huì)把向量變成一維矩陣境肾,第二次t(t(·))
才會(huì)轉(zhuǎn)置剔难。例如:
V <- c(1:3)
class(V)
## [1] "integer"
class(t(V))
## [1] "matrix" "array"
M <- matrix(c(1:6), ncol=3)
t(M)
## [,1] [,2]
## [1,] 1 2
## [2,] 3 4
## [3,] 5 6
t(mtcars[1:3,1:3])
## Mazda RX4 Mazda RX4 Wag Datsun 710
## mpg 21 21 22.8
## cyl 6 6 4.0
## disp 160 160 108.0
5.6.2 整合數(shù)據(jù)
在R中使用一個(gè)或多個(gè)by
和一個(gè)預(yù)先定義好的函數(shù)來折疊(collapse)數(shù)據(jù)是比較容易的,語法是:
aggregate(x, by=list(...), FUN)
其中x
是待折疊的對(duì)象奥喻;by
是一個(gè)變量名組成的列表偶宫;FUN
是預(yù)先定義好的用來計(jì)算描述性統(tǒng)計(jì)量的標(biāo)量函數(shù)。
例如环鲤,我們根據(jù)氣缸數(shù)(cyl)和檔位數(shù)(gear)整合mtcars數(shù)據(jù)读宙,并返回個(gè)數(shù)值型變量的均值:
options(digits = 3)
attach(mtcars)
aggdata <- aggregate(mtcars, by=list(cyl, gear), FUN=mean, na.rm=TRUE)
aggdata
## Group.1 Group.2 mpg cyl disp hp drat wt qsec vs am gear carb
## 1 4 3 21.5 4 120 97 3.70 2.46 20.0 1.0 0.00 3 1.00
## 2 6 3 19.8 6 242 108 2.92 3.34 19.8 1.0 0.00 3 1.00
## 3 8 3 15.1 8 358 194 3.12 4.10 17.1 0.0 0.00 3 3.08
## 4 4 4 26.9 4 103 76 4.11 2.38 19.6 1.0 0.75 4 1.50
## 5 6 4 19.8 6 164 116 3.91 3.09 17.7 0.5 0.50 4 4.00
## 6 4 5 28.2 4 108 102 4.10 1.83 16.8 0.5 1.00 5 2.00
## 7 6 5 19.7 6 145 175 3.62 2.77 15.5 0.0 1.00 5 6.00
## 8 8 5 15.4 8 326 300 3.88 3.37 14.6 0.0 1.00 5 6.00
其中,Group.1
表示氣缸數(shù)(4楔绞、6结闸、8)唇兑;Group.2
表示檔位數(shù)(3、4桦锄、5)扎附。這里返回的列表表示,
- 平均來看结耀,有4個(gè)氣缸留夜,3個(gè)檔位的的車型每加侖汽油行駛英里數(shù)(mpg)為21.5
你也可以在by=list()
中指定變量的名稱,比如:
options(digits = 3)
attach(mtcars)
## The following objects are masked from mtcars (pos = 3):
##
## am, carb, cyl, disp, drat, gear, hp, mpg, qsec, vs, wt
aggdata <- aggregate(mtcars, by=list(Group.cyl=cyl, Group.gears=gear), FUN=mean, na.rm=TRUE)
aggdata
## Group.cyl Group.gears mpg cyl disp hp drat wt qsec vs am gear carb
## 1 4 3 21.5 4 120 97 3.70 2.46 20.0 1.0 0.00 3 1.00
## 2 6 3 19.8 6 242 108 2.92 3.34 19.8 1.0 0.00 3 1.00
## 3 8 3 15.1 8 358 194 3.12 4.10 17.1 0.0 0.00 3 3.08
## 4 4 4 26.9 4 103 76 4.11 2.38 19.6 1.0 0.75 4 1.50
## 5 6 4 19.8 6 164 116 3.91 3.09 17.7 0.5 0.50 4 4.00
## 6 4 5 28.2 4 108 102 4.10 1.83 16.8 0.5 1.00 5 2.00
## 7 6 5 19.7 6 145 175 3.62 2.77 15.5 0.0 1.00 5 6.00
## 8 8 5 15.4 8 326 300 3.88 3.37 14.6 0.0 1.00 5 6.00
5.6.3 reshape2包
reshape2包是一套重構(gòu)和整合數(shù)據(jù)集的萬能工具图甜,但用起來有點(diǎn)復(fù)雜碍粥。我們首先要安裝reshape2包:
install.packages("reshape2")
然后用下面的例子來簡(jiǎn)要介紹reshape2包。
ID <- c(1,1,2,2)
Time <- c(1,2,1,2)
X1 <- c(5,3,6,2)
X2 <- c(6,5,1,4)
mydata <- data.frame(ID, Time, X1, X2)
mydata
## ID Time X1 X2
## 1 1 1 5 6
## 2 1 2 3 5
## 3 2 1 6 1
## 4 2 2 2 4
1. 融合
數(shù)據(jù)集的融合是將其重構(gòu)為這樣的格式:
每個(gè)測(cè)量變量獨(dú)占一行黑毅,行中帶有唯一確定這個(gè)測(cè)量所需的標(biāo)識(shí)符變量
上面的mydata
可以使用下面的代碼進(jìn)行重構(gòu):
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.0.2
md <- melt(mydata, id=c("ID", "Time"))
md
## ID Time variable value
## 1 1 1 X1 5
## 2 1 2 X1 3
## 3 2 1 X1 6
## 4 2 2 X1 2
## 5 1 1 X2 6
## 6 1 2 X2 5
## 7 2 1 X2 1
## 8 2 2 X2 4
注意嚼摩,必須指定唯一確定每個(gè)變量所需的變量(在這里是ID和Time),而表示測(cè)量變量名的變量(X1, X2)將由程序?yàn)槟阕詣?dòng)創(chuàng)建矿瘦。
2. 重構(gòu)
使用dcast()
命令重構(gòu)融合后的數(shù)據(jù)枕面,并使用你提供的一個(gè)公式和一個(gè)(可選的)用于整個(gè)數(shù)據(jù)的函數(shù)將其重構(gòu),調(diào)用的語法是:
newdata <- dcast(md, formula, fun.aggregate)
在這里缚去,md
是已經(jīng)融合的數(shù)據(jù)潮秘;formula
描述了想要的最后結(jié)果;fun.aggregate
是數(shù)據(jù)整合函數(shù)易结。其中枕荞,formula
的格式為
rowvar1 + rowvar2 + ... ~ colvar1 + colvar2 + ...
其中,rowvar1 + rowvar2 + ...
定義了行標(biāo)簽搞动,以確定各行的內(nèi)容买猖;colvar1 + colvar2 + ...
則列表標(biāo)簽,定義了各列的內(nèi)容滋尉,比如:
dcast(md, ID+Time~variable)
## ID Time X1 X2
## 1 1 1 5 6
## 2 1 2 3 5
## 3 2 1 6 1
## 4 2 2 2 4
dcast(md, ID+variable~Time)
## ID variable 1 2
## 1 1 X1 5 3
## 2 1 X2 6 5
## 3 2 X1 6 2
## 4 2 X2 1 4