R語言編程藝術,第一章:快速入門
1.生成n個基於N(0,1)分佈的隨機數rnorm(n)
取絕對值abs(),
取平均值mean(),
取標準差sd()
2.使用批處理命令:把下列命令保存在z.R的文件中
pdf(「xh.pdf」) #保存爲pdf格式的圖形文件並命名爲xh.pdf
hist(rnorm(100)) #調用hist函數生成直方圖
dev.off() #關閉圖形設備,即把生成的圖形文件存盤
如何調用呢?
R CMD BATCH z.R
3.建立一個向量:
x <- c(1,2,4) #c是鏈接的意思
q <- c(x,x,8) #能夠建立包括向量的向量 q爲 1 2 4 1 2 4 8
4.元素的索引: R是從1開始索引的
x[3]表示的時索引向量中的第三個元素
索引片斷:x[2:3]
能夠把這些索引值存儲在片斷中,使用賦值符號<-使用註釋是一個好的習慣,在R中的交互式命令中也可使用,由於查看歷史命令能夠幫助你回憶當時是怎麼思考的
5.R會內置一部分數據集,使用data()查看
6.q()退出,注意在大型的數據集中,最好保存歷史會話 編程
二 函數入門
1.計算向量中餘數的個數數組
oddcount <- function(x){ k <- 0 # 給計數器賦初值 for(n in x){ if(n %% 2 == 1) k <- k+1 # R的取餘爲 %% } return (k) }
2.在函數內部使用的變量都是局部變量,他們在函數返回值以後就撤消了
全局變量則是在函數以外建立的變量,在函數內部也能夠訪問:
f <- function(x) return(x+y) #定義函數
y <- 3
f(5)的結果是 8
3.關於函數調用,賦值的問題,先給定一個函數:
f <- function(x=1,y,z) return(x+y+z)
雖然函數缺省x的值,可是調用時還要當心
f(2,3) #函數將把2從新賦給x,把3賦給y,z沒有值,錯誤
f(y=2,z=3) #指明變量的值,正確
f(2,2,3) #函數將從新把x的值賦爲2,而後y是2,z是3
4.列表list
建立一個列表吧
x <- list(u=2,v="abc")
索引列表中的值用$
x$u
5.矩陣
如何建立矩陣?
行綁定:rbind() 即按行綁定:
m <- rbind(c(1,4),c(2,2))
> m
[,1] [,2]
[1,] 1 4
[2,] 2 2
列綁定:cbind() 按列綁定:
n <- cbind(c(1,4),c(2,2))
> n
[,1] [,2]
[1,] 1 2
[2,] 4 2
6.混合型的數據矩陣稱爲數據框
d <- data.frame(list(kids=c("Jack","Jill"),ages=c(12,10)))
> d
kids ages
1 Jack 12
2 Jill 10app
1.添加或刪除向量元素
實際上就是從新對變量賦值
x <- c(1,2,3,5)
x <- c(x[1:3],4,x[4]) #我想添加一個向量元素4使之變成(1,2,3,4,5)
x <- c(x[1:3]) #我想刪除一個向量元素5使之變成(1,2,3)
2.關於循環的再認識
循環的目的是什麼?是遍歷向量中各個元素的值?仍是不只要求值還想要取得該元素的序列?
若是隻要求使用元素的值,使用下列的寫法:
for(n in x){
statement }
若是不僅僅要求值,還要取得元素的索引號,使用下面的寫法:
for (i in 1:length(x)){
statement } #這裏的x[i]與上面的n相同,表明向量中各個元素的可能取值
3.遍歷取值的時候,應避免向量元素個數小於1
正常狀況下是這樣的:
x <- c(1,2,3)
> 1:length(x)
[1] 1 2 3
若是是這樣:
x <- c()
> 1:length(x)
[1] 1 0 #這明顯不是咱們想要的結果
4.矩陣在內存序列中是如何儲存的?
是按列存儲的,不管是如何生成矩陣的,是按列綁定cbind,仍是按行綁定rbind,在內存序列中
都是按列存儲的
如何驗證?
m <- rbind(c(1,2),c(3,4)) #這裏的矩陣m是按行綁定生成的
> m
[,1] [,2]
[1,] 1 2
[2,] 3 4
> m + 10:13
[,1] [,2]
[1,] 11 14
[2,] 14 17
顯然,矩陣m按列存儲爲一個四元向量(1,3,2,4),加上(10,11,12,13)獲得(11,14,14,17)
5.同多數腳本語言同樣,R不須要事先聲明變量,注意這裏的"不須要"只是其中的一種方法.
建立向量的另外一種方法:(聲明變量法)
y <- vector(length=2) #爲變量y分配兩個存儲空間,沒有賦值的狀況下,兩個都是FALSE
y[1] <- 5 #一旦對其中任何一個元素賦值,其它元素自動置爲0,此時y[2]爲0
y[2] <- 12 #生成一個(5,12)的二元向量
說明一下爲何須要上述的方法:若是在循環體中每次使用相似於y <- c(5,12)的賦值,會
減慢代碼的運行速度,所以使用上述方法在一開始就分配內存空間,而進入循環體後只是填充
空間.
另外一種方法就是常見的
y <- c(5,12)
6.循環補齊
(1)向量與向量相加
若是長度不相等,短的就會自動與長的補齊,
注意,這裏不是補零!而是循環補
c(1,2,3)
c(1,2,3,1,2) #補成5位的
c(1,2,3,1,2,3,1) #補成7位的
(2)向量與矩陣相加
注意,由於矩陣沒法循環補齊,故只能是短向量與長矩陣相加時,會出現短向量循環補齊
(3)矩陣與矩陣相加
只能是相同行和列的矩陣相加,不存在補齊的狀況!
7.索引不連續的向量
x <- c(1,5,2,0,5,6,7,8)
> x[c(1,3,4)] #索引x向量的第一位,第三位和第四位元素
[1] 1 2 0
> x[1:3] #索引連續元素的方法:x向量的前三個元素
[1] 1 5 2
> x[c(1,1)] #重複索引第一位的元素
[1] 1 1
以上都是對R說我想要某某元素,還有一種方法是:我不想要某某元素,其它的都要:
> x[c(-1)] #除了第一位元素,其它都要
[1] 5 2 0 5 6 7 8
> x[c(-3:-5)] #除了第三到第五位元素,其它都要
[1] 1 5 6 7 8
8.建立向量
回憶下咱們目前知道的建立向量的方法:
x <- c(1,2,3,4,5,7,5,9)
若是想建立連續值得向量(注意他們的步進都是1):
x <- 1:8 #正向
x <- 5:-2 #負向
想改變步進的大小?沒問題,使用seq()函數:
x <- seq(from=12,to=29,by=3)
> x #注意這裏終止於27,而不是29,由於它們之間的間隔小於步進3
[1] 12 15 18 21 24 27 #上述函數能夠理解爲生成開始於12,步進爲3,最大不超過29的序列
一樣生成負向的序列:
> seq(from=0.8,to=-0.1,length=10) #這裏規定了向量的總長度,自動計算步進
[1] 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0.0 -0.1
seq()的另外一個做用:
seq(x)與1:length(x)的做用相同,甚至更優,由於對於空值x
x <- c()
> 1:length(x)
[1] 1 0 #這明顯不是咱們想要的結果
> seq(x)
integer(0) #該結果會是上面循環迭代0次,符合咱們的指望
建立重複序列的向量:rep(x,times)
> rep(c(1,3,8),4)
[1] 1 3 8 1 3 8 1 3 8 1 3 8
> rep(c(1,3,8),each=4) #每一個元素重複4遍
[1] 1 1 1 1 3 3 3 3 8 8 8 8
9.布爾值求解any(),all()
x <- 1:9
> any(x>5) #x中有>5的元素嗎?
[1] TRUE
> all(x>5) #x中全部元素都>5嗎?
[1] FALSE
實例一:尋找連續出現1的遊程
x <- c(1,0,0,1,1,1,0,1,1)
函數
#version 1.0 findruns <- function(x,k){ #k是指連續出現1的個數 n <- length(x) runs <- NULL for (i in 1:(n-k+1)){ #爲何不是1:n?由於要保證連續的k個數比較 if(all(x[i:(i+k-1)]==1)) #這個判斷值真的是太絕妙了! runs <- c(runs,i) #重複賦值,可能會拖慢代碼的運行速度 } return(runs) }
#version 2.0 findruns <- function(x,k){ n <- length(x) runs <- vector(length=n) #不一樣於上個版本的地方,先聲明runs的變量 count <- 0 #爲runs分配的空間是用不完的,count計算用了多少位 for (i in 1:(n-k+1)){ if (all(x[i:(i+k-1)]==1)){ count <- count + 1 runs[count] <- i #這裏count也充當runs的序列索引號 } } if (count > 0){ runs <- runs[1:count] #釋放未利用的內存空間 } else runs <- NULL return (runs) }
實例二:預測離散值時間序列ui
preda <- function(x,y){ n <- length(x) k2 <- k/2 #若是在連續k天內1的數量>= k/2 pred <- vector(length=n-k) for (i in 1:(n-k)) { if (sum(x[i:(i+k-1)]) >= k2) #若是在連續k天內1的數量>= k/2 pred[i] <- 1 #那麼預測下一個值爲1 else pred[i] <- 0 } return(mean(abs(pred-x[(k+1):n]))) }
但在實際中不多用諸如
sum(x[i:(i+k-1)])計算連續k個元素之和,由於重複計算,這會拖慢代碼速度
咱們可使用cumsum()函數代替:cumsum是計算向量的累積和
y <- c(5,2,-3,8)
> cumsum(y)
[1] 5 7 4 12
好比我想計算第二個到第四個數的和
x <- cumsum(y)
x[4] - x[1]
那第一個到第三個數之和呢? 爲了統一形式:
x[3] - x[0] 但R中向量元素是從零開始索引的,爲了形式上的統一
咱們使用以下辦法:
csx <- c(0,cumsum(y))
這樣以來咱們就能夠寫成
csx[4] - scx[1] 來表示向量元素中第一個數到第三個數之和
基於此,咱們更改第一個版本的代碼:spa
preda <- function(x,y){ n <- length(x) k2 <- k/2 #若是在連續k天內1的數量>= k/2 pred <- vector(length=n-k) csx <- c(0,cumsum(x)) #新添的代碼! for (i in 1:(n-k)) { if (csx[i+k] - csx[i] >= k2) #若是令i=1,k=3,該語句即爲csx[4] - csx[1] #來表示向量元素中第一個數到第三個數之和 pred[i] <- 1 #那麼預測下一個值爲1 else pred[i] <- 0 } return(mean(abs(pred-x[(k+1):n]))) }
第三章:矩陣和數組
1.如何建立矩陣
> y <- matrix(c(1,2,3,4),nrow=2,ncol=2) #矩陣在R中是按列存儲的
> y
[,1] [,2]
[1,] 1 3
[2,] 2 4
該方法與以前的經過行(列)綁定的方法無異:
> x <- cbind(c(1,2),c(3,4))
> x
[,1] [,2]
[1,] 1 3
[2,] 2 4
> all(x==y)
[1] TRUE
錄入數據時,有時但願錄入的數據元素能夠按行排列,
這時只需令 byrow=1 便可,可是注意,矩陣在R中依然是按列存儲的
> m <- matrix(c(1,2,3,4,5,6),nrow=2,byrow=1)
> m
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
相似於向量的建立,矩陣還能夠先聲明,再賦值
> y <- matrix(nrow=2,ncol=2)
> y
[,1] [,2]
[1,] NA NA
[2,] NA NA
> y[1,1] <- 1
> y[1,2] <- 3
> y[2,1] <- 2
> y[2,2] <- 4
> y
[,1] [,2]
[1,] 1 3
[2,] 2 4code
2.通常矩陣運算
這裏先介紹三種:
數量乘法運算:3*y
矩陣相加運算:y+y
矩陣相乘運算:y %*% yorm
3.矩陣索引:
列索引: z[,2:3] #索引z矩陣的全部行,第二到第三列
行索引: z[2:3,] #索引z矩陣的第二到第三列,全部的列
不連續行的索引: z[c(1,3),]
負值索引:即索引除去該值外的全部元素
> y <- matrix(c(1,2,3,4,5,6),ncol=2) #只規定行或列便可
> y
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
> y[-2,] #索引y矩陣除第二行外的全部元素
[,1] [,2]
[1,] 1 4
[2,] 3 6blog
4.改變矩陣的值
> m
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
> m[,c(1,3)] <- matrix(c(1,2,3,4),nrow =2)
> m
[,1] [,2] [,3]
[1,] 1 2 3排序
5.矩陣元素的篩選:
> y
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
> y[y[,2]>=5,] #篩選出y矩陣中第二列>=5的全部行,並組成全部新的矩陣
[,1] [,2]
[1,] 2 5
[2,] 3 6
擴展案例:如何生成協方差矩陣?
makecov <- function(rho,n){ m <- matrix(nrow=n,ncol=n) #聲明一個n行n列的矩陣 m <- ifelse(row(m)==col(m),1,rho) #對角線元素爲1,其它位置是協方差係數 return(m) }
> makecov(0.2,3)
[,1] [,2] [,3]
[1,] 1.0 0.2 0.2
[2,] 0.2 1.0 0.2
[3,] 0.2 0.2 1.0
6.apply()函數
有時咱們要對矩陣的行或列作這樣或那樣的運算,apply()函數就派上用場了,
apply函數有三個參數apply(m,dimcode,f,fargs)
m 矩陣名稱
dimcode:只有兩個值,1把函數運用到每一行,2把函數運用到每一列
f 運用到每行或每列的函數
fargs 函數的參數
> copymaj <- function(rw,d){
+ maj <- sum(rw[1:d])/d #計算每行前d個數的平均值
+ return(ifelse(maj>0.5,1,0)) #>0.5返回1,不然返回0
+ }
> x <- matrix(c(1,0,1,1,0,1,1,1,1,0,1,0,0,1,1,0,1,1,1,0),nrow=4,byrow=T)
> x #參數byrow=T表示錄入的元素按行排列
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 1 1 0
[2,] 1 1 1 1 0
[3,] 1 0 0 1 1
[4,] 0 1 1 1 0
> apply(x,1,copymaj,3)
[1] 1 1 0 1 #每行的結果都是按列存儲的,共有4行,因此結果是4列
> apply(x,1,copymaj,2)
[1] 0 1 0 0
> apply(x,2,copymaj,2) #對矩陣的每列進行運算,矩陣有5列,結果也是5列
[1] 1 0 1 1 0
> apply(x,2,copymaj,3)
[1] 1 0 1 1 0
擴展案例:尋找異常值:
findols <- function(x){ findol <- function(xrow){ mdn <- median(xrow) #尋找每一行的中位數 devs <- abs(xrow - mdn) #把每一行元素與中位數的差值賦給devs向量 return(which.max(devs)) #找到devs向量中最大元素的位置 } return(apply(x,1,findol)) #把findol函數用到x矩陣的每一行 }
> y <- matrix(c(1,4,6,3,2,5,7,29,53,76,3,2,1,987,3,56,54,22,2,1,8),nrow=3,byrow=T)
> y
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1 4 6 3 2 5 7
[2,] 29 53 76 3 2 1 987
[3,] 3 56 54 22 2 1 8
> findols(y)
[1] 1 7 2
7.和向量同樣,在循環中重複不斷的建立矩陣是很浪費時間的行爲,
一個比較好的辦法就是,在循環體外先聲明一個空的矩陣,
而後在循環中爲矩陣賦值
8.避免意外降維
當咱們從某一矩陣抽取其中的一行做爲子矩陣時,獲得的卻變爲了一個向量,
> z <- matrix(1:8,nrow=4)
> z
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
> r <- z[2,]
> r
[1] 2 6
由於這裏
> nrow(r)
NULL #故r是一個向量,這與咱們的預期不符,
解決辦法就是使用drop參數
> r <- z[2,,drop=FALSE]
> r
[,1] [,2]
[1,] 2 6
此時有:
> nrow(r)
[1] 1
這裏提供另外的一個小技巧:把向量變爲矩陣as.matrix()
> u <- 1:3
> u
[1] 1 2 3
> as.matrix(u)
[,1]
[1,] 1
[2,] 2
[3,] 3
9.給矩陣的行或列取名字
> z
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
> colnames(z) <- c("a","b") #給z矩陣的列從新命名
> z
a b
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
> rownames(z) <- c("甲","乙","丙","丁") #給z矩陣的行從新命名
> z
a b
甲 1 5
乙 2 6
丙 3 7
丁 4 8
不過索引的時候也要加上引號:
> z[c("甲","丙"),]
a b
甲 1 5
丙 3 7
10.高維數組
高維數組其實就是矩陣的集合,有三個維度
生成一個高維的數組:
> firsttest <- matrix(c(46,21,50,30,25,50),nrow=3)
> secondtest <- matrix(c(46,41,50,43,35,50),ncol=2)
> firsttest
[,1] [,2]
[1,] 46 30
[2,] 21 25
[3,] 50 50
> secondtest
[,1] [,2]
[1,] 46 43
[2,] 41 35
[3,] 50 50
> tests <- array(data=c(firsttest,secondtest),dim=c(3,2,2))
> tests #注意array中,有數據data部分和維度dim部分
, , 1 #其中dim=c(x,y,n)中的n是data=c(a,b,c,...)中的矩陣個數
[,1] [,2]
[1,] 46 30
[2,] 21 25
[3,] 50 50
, , 2
[,1] [,2]
[1,] 46 43
[2,] 41 35
[3,] 50 50
第四章 列表
1.一個簡單地列表以下:
> j <- list(name="Joe",salary=55000,union=T)
> j
$name #各組件的名字叫作"標籤"(能夠不指定)
[1] "Joe"
$salary #標籤
[1] 55000
$union #標籤
[1] TRUE
由於列表是向量,故能夠用vector建立列表:
> z <- vector(mode="list") #聲明一個模式是"列表"的向量
> z[["name"]] <- "Pony" #而後能夠給列表不斷的賦值
> z[["salary"]] <- 33
...
2.三種方法索引列表中的各組件:
> j$name #列表名+$+組件名稱
[1] "Joe"
> j[[1]] #列表名後跟雙層中括號,括號內爲索引組件在列表中得序號
[1] "Joe"
> j[["name"]] #列表名後跟雙層中括號,括號內爲帶有雙引號的組件名稱
[1] "Joe"
#注意與使用單層中括號的區別
> j["name"] #使用單層中括號返回的是該組件及組件的內容,能夠視爲一個子列表
$name #使用雙層中括號返回的是該組件的內容
[1] "Joe"
3.增長或刪除列表元素:這裏的列表元素指的是組件
只能增長或刪除組件,而後給組件賦值
> z <- list(a="abc",b=12)
> z
$a
[1] "abc"
$b
[1] 12
> z$c <- "sailing" #增長一個組件c並賦值爲sailing
> z
$a
[1] "abc"
$b
[1] 12
$c #增長的組件c
[1] "sailing" #及內容
如何刪除組件b呢?
只需給組件b賦值爲NULL便可
> z$b <- NULL #刪除組件b的一種方法
> z
$a
[1] "abc"
$c #注意刪除一個組件後,其它組件在列表中的序號可能會發生變更
[1] "sailing"
注意隱藏的類型轉換
> z[1:3] <- c(168,"Cool",TRUE) #z中各組件的內容所有被視爲character型
> z
[[1]]
[1] "168"
[[2]]
[1] "Cool"
[[3]]
[1] "TRUE"
> class(z[[3]])
[1] "character"
> z[1:3] <- c(168,FALSE,TRUE) #z中各組件的內容所有被視爲numeric型
> z
[[1]]
[1] 168
[[2]]
[1] 0
[[3]]
[1] 1
> class(z[[3]])
[1] "numeric"
> z[1:3] <- c(TRUE,FALSE,TRUE) #這個固然都爲爲logical型
> z
[[1]]
[1] TRUE
[[2]]
[1] FALSE
[[3]]
[1] TRUE
> class(z[[3]])
[1] "logical"
上面三個例子說明了什麼?
當要建立一個列表時,若是使用索引添加新組件,則c()中的內容會被置爲統一數據類型
此時應加以關注,避免產生非預期的結果!
最後,還能夠把多個列表拼接成一個:
> c(list("Joe",55000,T),list(5))
[[1]]
[1] "Joe"
[[2]]
[1] 55000
[[3]]
[1] TRUE
[[4]]
[1] 5
給同一個組件添加多個值:
> z[[1]] <- c(z[[1]],123)
> z
[[1]]
[1] "168" "123" #組件1中含有兩個值
[[2]]
[1] "Cool"
[[3]]
[1] "TRUE"
4.訪問列表元素和值
獲取組件名稱:標籤
> names(j)
[1] "name" "salary" "union"
去列表化:unlist()
在去列表化的時候,只要有可能,列表的元素都強制被轉換成一種共同存儲模式
> wu <- unlist(j)
> wu
name salary union
"Pony" "55000" "TRUE"
> class(wu)
[1] "character"
這裏的wu實際是帶有名字的字符串向量,爲使看起來更像向量,能夠把名字置空
> names(wu) <- NULL #另外一種方法是去名字化: unname()
> wu
[1] "Pony" "55000" "TRUE"
5.在列表上使用apply()函數
lapply()把函數應用到每個列表元素中:
> j <- list(1:3,25:27) #生成一個具備兩個元素的列表
> j
[[1]]
[1] 1 2 3
[[2]]
[1] 25 26 27
> lapply(j,median) #對列表中每一個元素應用median函數
[[1]]
[1] 2
[[2]]
[1] 26
若是想把返回的結果轉化成矩陣或向量形式,則可使用sapply()
> sapply(j,median)
[1] 2 26
6.遞歸型列表
> b <- list(u=5,v=12)
> c <- list(w=13)
> a <- list("A"=b,"B"=c)
> a
$A
$A$u #第一個組件A中包含u組件
[1] 5
$A$v #和v組件
[1] 12
$B #第二個組件B中包含w組件
$B$w
[1] 13
第五章:數據框
1.建立數據框
> kids <- c("Jack","Jill")
> ages <- c(12,10)
> d <- data.frame(kids,ages) #建立數據框使用data.frame(col1,col2,col3...)
> d #其中列向量col1,col2,...能夠是任何數據類型
kids ages
1 Jack 12
2 Jill 10
2.訪問數據框中各組件
> d$kids #和列表的方式同樣
[1] Jack Jill
Levels: Jack Jill
> d[[1]]
[1] Jack Jill
Levels: Jack Jill
> str(d) #str()函數查看d的內部結構
'data.frame': 2 obs. of 2 variables:
$ kids: Factor w/ 2 levels "Jack","Jill": 1 2
$ ages: num 12 10
3.提取子數據框
首先建立一個考試成績的數據框
> Exam.1 <- c(2.0,3.3,4.0,2.3,2.3,3.3)
> Exam.2 <- c(3.3,2.0,4.0,0.0,1.0,3.7)
> Quiz <- c(4.0,3.7,4.0,3.3,3.3,4.0)
> examsquiz <- data.frame(Exam.1,Exam.2,Quiz)
> examsquiz
Exam.1 Exam.2 Quiz
1 2.0 3.3 4.0
2 3.3 2.0 3.7
3 4.0 4.0 4.0
4 2.3 0.0 3.3
5 2.3 1.0 3.3
6 3.3 3.7 4.0 
> examsquiz[2:5,] #提取2到5行
Exam.1 Exam.2 Quiz
2 3.3 2 3.7
3 4.0 4 4.0
4 2.3 0 3.3
5 2.3 1 3.3
> examsquiz[2:5,2,drop=FALSE] #爲了不"降維",使用"drop=FALSE"這個參數
Exam.2
2 2
3 4
4 0
5 1
數據篩選
> examsquiz[examsquiz$Exam.1>=3,]
Exam.1 Exam.2 Quiz
2 3.3 2.0 3.7
3 4.0 4.0 4.0
6 3.3 3.7 4.0
或者使用subset()函數
> subset(examsquiz,Exam.1>=2.8)
Exam.1 Exam.2 Quiz
2 3.3 2.0 3.7
3 4.0 4.0 4.0
6 3.3 3.7 4.0
4.缺失值NA的處理
咱們爲examsquiz添加一行帶有NA的數據
> examsquiz <- rbind(examsquiz,list(3.7,NA,3.8))
> examsquiz
Exam.1 Exam.2 Quiz
1 2.0 3.3 4.0
2 3.3 2.0 3.7
3 4.0 4.0 4.0
4 2.3 0.0 3.3
5 2.3 1.0 3.3
6 3.3 3.7 4.0
7 3.7 NA 3.8
計算每一列的平均值:
> apply(examsquiz,2,mean)
Exam.1 Exam.2 Quiz
2.985714 NA 3.728571
第二列的均值居然是NA!這顯然不是咱們所指望的,
咱們能夠爲mean函數增長一個參數使之能夠忽視NA
> apply(examsquiz,2,mean,na.rm=TRUE)
Exam.1 Exam.2 Quiz
2.985714 2.333333 3.728571 #計算Exam.2的均值時忽視了第七個學生的成績
5.爲數據框添加新的列(行)的另外一種方法
上面已展現瞭如何使用rbind()或cbind()爲數據框增添元素
還可使用這樣:
> examsquiz$Examdiff <- examsquiz$Exam.1 - examsquiz$Exam.2
> examsquiz
Exam.1 Exam.2 Quiz Examdiff
1 2.0 3.3 4.0 -1.3
2 3.3 2.0 3.7 1.3
3 4.0 4.0 4.0 0.0
4 2.3 0.0 3.3 2.3
5 2.3 1.0 3.3 1.3
6 3.3 3.7 4.0 -0.4
7 3.7 NA 3.8 NA
6.上面的NA看着很討厭人,這裏有一個方法去除
> examsquiz[complete.cases(examsquiz),]
Exam.1 Exam.2 Quiz Examdiff
1 2.0 3.3 4.0 -1.3
2 3.3 2.0 3.7 1.3
3 4.0 4.0 4.0 0.0
4 2.3 0.0 3.3 2.3
5 2.3 1.0 3.3 1.3
6 3.3 3.7 4.0 -0.4
這裏的complete.cases()做用是這樣的:
> complete.cases(examsquiz)
[1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE
能夠檢測出哪一行的數據是不完整的
7.合併數據框
先給出兩個含有相同元素的數據框
> d1 <- data.frame(kids=c("Jalk","Jill","Jillian","John"),states=c("CA","MA","MA","HI"))
> d1
kids states
1 Jack CA
2 Jill MA
3 Jillian MA
4 John HI
> d2 <- data.frame(ages=c(10,7,12),kids=c("Jill","Lillian","Jack"))
> d2
ages kids
1 10 Jill
2 7 Lillian
3 12 Jack
合併
> d <- merge(d1,d2) #這兩個數據框中都有kids這個組件,合併相同的值"Jack","Jill"
> d
kids states ages #組件states來自於d1,組件ages來自於d2
1 Jack CA 12
2 Jill MA 10
另外一種狀況是:即便組件名字不一樣,可是內容同樣時,依然能夠經過一種方法合併
> d3 <- data.frame(pals=c("Jack","Jill","Lillian"),ages=c(12,10,7))
> d3
pals ages
1 Jack 12
2 Jill 10
3 Lillian 7
> d1 <- cbind(d1,ages=c(10,7,12,9))
> d1
kids states ages
1 Jack CA 10
2 Jill MA 7
3 Jillian MA 12
4 John HI 9
> merge(d1,d3,by.x="kids",by.y="pals")
kids states ages.x ages.y #把d1中的kids與d2中的pals進行合併
1 Jack CA 10 12
2 Jill MA 7 10
但若是兩個數據框含有兩個或兩個以上的組件,且各有相同的值,那麼如何肯定合併
的組件?
> d1
kids states ages
1 Jack CA 10
2 Jill MA 7
3 Jillian MA 12
4 John HI 9
> d2
ages kids
1 10 Jill
2 7 John
3 12 Jack
> merge(d1,d2) #R也不知該按kids合併仍是按ages合併了
[1] kids ages states
<0 行> (或0-長度的row.names)
這時,能夠加個參數用於指定按哪一個組件進行合併
> merge(d1,d2,by.x="kids",by.y="kids") #把d1中的kids與d2中的kids合併
kids states ages.x ages.y
1 Jack CA 10 12
2 Jill MA 7 10
3 John HI 9 7
> merge(d1,d2,by.x="ages",by.y="ages") #把d1中的ages與d2中的ages合併
ages kids.x states kids.y
1 7 Jill MA John
2 10 Jack CA Jill
3 12 Jillian MA Jack
但這個數據框好像只能應用於兩個數據框,我試驗了三個,但直接被無視了:
> d3
pals ages
1 Jack 3
2 Jill 6
3 Lillian 8
> merge(d1,d2,d3,by.x="kids",by.y="kids",by.z="pals")
kids states ages.x ages.y #d3中的數據未被合併進來
1 Jack CA 10 12
2 Jill MA 7 10
3 John HI 9 7
8.應用於數據框的函數
> d1
kids states ages
1 Jack CA 10
2 Jill MA 7
3 Jillian MA 12
4 John HI 9
> lapply(d1,sort) #對數據框的每列進行排序,返回的是列表
$kids
[1] "Jack" "Jill" "Jillian" "John"
$states
[1] CA HI MA MA
Levels: CA HI MA
$ages
[1] 7 9 10 12
> as.data.frame(lapply(d1,sort)) #把列表轉化成數據框,但結果沒什麼意義了
kids states ages
1 Jack CA 7
2 Jill HI 9
3 Jillian MA 10
4 John MA 12
第六章 因子和表
1.因子與水平
> e <- c(2,45,13,2,4,9,6,87,12,1,2,13)
> e
[1] 2 45 13 2 4 9 6 87 12 1 2 13
> ef <- factor(e) #把向量e轉化成因子ef
> ef #因子的結構包括如下:向量元素的值,向量的水平
[1] 2 45 13 2 4 9 6 87 12 1 2 13 #元素的值
Levels: 1 2 4 6 9 12 13 45 87 #按元素的值從小到大排列,且不重複.
> str(ef)
Factor w/ 9 levels "1","2","4","6",..: 2 8 7 2 3 5 4 9 6 1 ...
元素的值按水平位置的索引,好比2排在水平級的第二位,45排在水平級的第八位,
13排在水平級的第七位.
咱們在定義一個因子時,能夠經過定義水平而預置數據
> x <- c(5,12,13,12)
> xff <- factor(x,levels=c(5,12,13,18))
> xff
[1] 5 12 13 12
Levels: 5 12 13 18 #"水平級"告訴咱們,未來因子中有可能加入18這個值
> xff[2] <- 18
> xff
[1] 5 18 13 12
Levels: 5 12 13 18
而若加入一個水平級裏面沒有的值,可能會獲得一個警告,而且不會成功
> xff[2] <- 88
警告信息:
In `[<-.factor`(`*tmp*`, 2, value = 88) :
invalid factor level, NA generated
> xff
[1] 5 <NA> 13 12 #88未被加入
Levels: 5 12 13 18
2.因子經常使用函數
tspply(x,f,g) #x是向量,f是因子或因子列表,g是函數
tapply()執行的操做是:將向量x按因子水平分組,獲得x的子向量,再把函數g應用到這些子向量中
> ages <- c(25,26,55,37,21,42)
> affils <- c("R","D","D","R","U","D")
> tapply(ages,affils,mean) #affils的因子水平,是D R U
D R U #x的子向量是D:26,55,42 R:25,37 U:21
41 31 21 #每一個子向量求平均得 D:41 R:31 U:21
> tapply(affils,ages,mean)
21 25 26 37 42 55 #不要把affils和ages弄反了,這個是錯誤的!!!
NA NA NA NA NA NA
警告信息:
1: In mean.default(X[[1L]], ...) : 參數不是數值也不是邏輯值:回覆NA
2: In mean.default(X[[2L]], ...) : 參數不是數值也不是邏輯值:回覆NA
3: In mean.default(X[[3L]], ...) : 參數不是數值也不是邏輯值:回覆NA
4: In mean.default(X[[4L]], ...) : 參數不是數值也不是邏輯值:回覆NA
5: In mean.default(X[[5L]], ...) : 參數不是數值也不是邏輯值:回覆NA
6: In mean.default(X[[6L]], ...) : 參數不是數值也不是邏輯值:回覆NA
一個含有兩個因子的例子:
> d <- data.frame(gender=c("M","M","F","M","F","F"),
+ age=c(47,59,21,32,33,24),
+ income=c(55000,88000,32450,76500,123000,45650))
> d #關於數據框的生成,若是使用data.frame(list(...))也是能夠的
gender age income
1 M 47 55000
2 M 59 88000
3 F 21 32450
4 M 32 76500
5 F 33 123000
6 F 24 45650
我想按性別及年齡是否超過25歲分組求平均,爲此咱們先爲數據框增長一個組件
> d$over25 <- ifelse(d$age>25,1,0)
> d
gender age income over25
1 M 47 55000 1
2 M 59 88000 1
3 F 21 32450 0
4 M 32 76500 1
5 F 33 123000 1
6 F 24 45650 0
按照性別,是否過25歲這兩個維度求平均:
> tapply(d$income,list(d$gender,d$over25),mean)
0 1
F 39050 123000.00
M NA 73166.67
固然,咱們能夠只按性別求平均:
> tapply(d$income,d$gender,mean)
F M
67033.33 73166.67
也能夠只按是否過25歲求平均:
> tapply(d$income,d$over25,mean)
0 1
39050 85625
split()函數
類比於tapply(),split()只作到:將向量x按因子水平分組,獲得x的子向量這一步就結束了
> split(d$income,d$gender)
$F #女性的收入
[1] 32450 123000 45650
$M #男性的收入
[1] 55000 88000 76500
> split(d$income,list(d$over25,d$gender))
$`0.F` #未過25歲的女性的收入
[1] 32450 45650
$`1.F` #25歲以上女性的收入
[1] 123000
$`0.M` #不到25歲男性的收入
numeric(0)
$`1.M` #25歲以上男性的收入
[1] 55000 88000 76500
使用split()能夠快速索引文本詞彙出現的位置
split(1:length(txt),txt) #txt是一個包括全部文本詞彙的因子
by()的調用方式與tapply()相似,不一樣的是,tapply的第一個參數必須是向量,而by()支持矩陣
和數據框
3.表的操做
> f1 <- list(c(5,12,13,12,13,5,13),c("a","b","a","a","b","a","a"))
> table(f1) #表返回的是因子f1中各元素的頻數
f1.2
f1.1 a b
5 2 0
12 1 1
13 2 1
再來看一個三維的表:
> v <- data.frame(gender=c("M","M","F","M","F","F"),race=c("W","W","A","O","B","B"),pol=c("L","L","C","L","L","C"))
> v
gender race pol
1 M W L
2 M W L
3 F A C
4 M O L
5 F B L
6 F B C
> vt <- table(v) #表是以二維的結構展現的
> vt
, , pol = C
race
gender A B O W
F 1 1 0 0
M 0 0 0 0
, , pol = L
race
gender A B O W
F 0 1 0 0
M 0 0 1 2
使用addmargins()函數計算表的邊際值:
> table(f1)
f1.2
f1.1 a b
5 2 0
12 1 1
13 2 1
> addmargins(table(f1))
f1.2
f1.1 a b Sum
5 2 0 2
12 1 1 2
13 2 1 3
Sum 5 2 7
使用dimnames()函數得到表的維度的名稱
> dimnames(table(f1))
$f1.1
[1] "5" "12" "13"
$f1.2 [1] "a" "b"