由於數據框的本質是由一堆向量或者因子構成的列表,其中的每個向量或者因子表明了一列。所以,數據框能夠包含不一樣類型的數據(數值型、布爾型或字符型),可是每一列的數據類型必須相同。數據庫
咱們能夠經過data.frame()函數將相同長度的向量數據,構建一個數據框數組
name <- c("Jane","Maria","kangkang","Micheal",'Yukio',"sansa") age <- c(15,14,15,15,16,14) country <- c("Canada","Cuba","China","American","Japan","American") info <- data.frame(name,age,country)
能夠經過as.data.frame將列表數據轉化成數據框app
info <- list(name = name,age = age,country = country) info <- as.data.frame(info)
經過read.csv()函數、read.table()函數讀入的表格文件,以及從數據庫讀入的數據都會返回一個數據框函數
# 查看第一列 info[,1] # 查看第一行 info[1,] # 查看第二行第三列 info[2,3]
info[1:2] # 查看第一至第二列 info[c("name","age")] # 查看列名爲name,age的列
若只查看數據的某一列還能夠經過 [[]] 和 $ui
info[[2]] # 查看數據的第二列,這和上面的列的下標查看很類似,可是返回的數據類型不一樣,上面返回的是數據框,這返回的是向量 info[["name"]] # 查看數據中中列名爲name的列,和上面列名查看類似,但返回的數據類型不一樣 info$name # 查看數據中的name列
上面提到咱們能夠經過 $ 訪問數據框某列,咱們也能夠經過 $ 向數據框添加某列3d
info$gender <- c("female","female","male","male","male","female") # 向info數據框中添加名爲gender列,列的數據必須和其它列的長度一致,若是不一致將自動循環補齊,而循環過程當中,長度必須爲整數倍 info$grade <- c("class 1","class 2","class 3") # 其餘列的長度爲6,是該向量的2倍,向量循環2次。等價於info$class <- c("class 1","class 2","class 3","class 1","class 2","class 3") info$grade <- c("class 1","class 2","class 3","class 4") # 非整數倍將出錯
能夠經過下標刪除行或列code
info[-1,] # 刪除第一行 info[,-1] # 刪除第一列
還能夠經過將某一列賦值爲NULL,來刪除該列orm
info$name <- NULL
另外還能夠按照條件索引、匹配等來刪除數據框的某行或者某列這部分見數據框匹配對象
names()函數能夠得到/命名一個對象的名稱。返回/設置的爲一個字符向量blog
names(info) <- c("newname","newage","newcountry","newgender","newgrade")
由於是字符操做,因此能夠運用字符穿的匹配,替換等操做結合向量元素替換操做來重命名
names(info)[names(info) == "name"] <- c("rename") # 以及names(info) == "name",獲取列名並判斷列名是否等同於name,而後names函數將與條件匹配的元素從新賦值爲"rename" names(info)[grep("name",names(info))] <- c("newname") names(info)[grepl("name",names(info))] <- c("newname") ...
經過列的下標排序。其實這個就是和數據框經過列的提取,而後將提取的列從新構成一個數據框而已。因此,最好細心,由於不當心就會把數據只獲得某幾列。以下面info數據框有5列,想調整第二列和第三輪的順序
info <- info[c(1,3,2)] # 此時至關於提取了原info數據框的第一列、第三列、第二列而後賦值給info。而第四列、第五列就刪除了 info <- info[c(1,3,2,4,5)] #應該將整個數據都提取,只是順序從新排列。這樣比較麻煩
另外能夠把下標替換爲列名,而後和下標同樣的用法
info <- info[c("name","country","age","gender","grade")]
subset()函數根據條件返回向量或矩陣或數據框
## S3 method for class 'data.frame' subset(x, subset, select, drop = FALSE, ...)
male <- subset(info,gender == "male") # gender == "male",由於subset必須是邏輯值,因此行的提取還能夠經過返回爲邏輯的字符匹配操做,來篩選 male <- subset(info,grepl("a",info$name)) # 提取info數據框中name列中元素帶字母a的行 male <- subset(info,gender == "male",select = c(gender,name,age)) # select 提取列,因此提取info 數據框中gender爲male的行,而後提取了gender,name,age這三列 newInfo <- subset(info,select = grep("a",names(info))) # 提取列名中含有字母a的列 male <- subset(info,gender == "male"|country == "china") #另外還能夠經過|(或)&(且)等進行跳進篩選 newInfo <- subset(info,age >= 15,select = grep("a",names(info))) #提取age中大於等於15的行,列名中含有字母a的列
subset是根據返回的邏輯值來匹配、提取。另外還能夠根據字符串下標來提取,咱們經過返回匹配值爲下標,而後根據該下標來提取或刪除。而咱們知道匹配字符串返回下標的函數有which、grep、str_which
newInfo <- info[which(info$name == "Jane"),] #提取info數據框name列中爲Jane的全部行。刪除的話是直接就是直接加刪除符號(-),行列都是同樣以用的 newInfo <- info[grep("Maria",info$name),3] # 提取info數據框name列中爲Maria的行,第三列。固然列也是能夠根據條件篩選的,只須要匹配函數返回的是下標 newInfo <- info[str_which(info$name,"sansa"),grep("gender",names(info)] # 提取info數據框name列中爲sansa的行,列名爲gender的列 newInfo <- info[grep(".*?(a).*?",info$name),] # 提取name中包含字符 a 的行
固然這是很小的數據,可是,假如咱們手裏有幾千個基因的數據,老闆甩給你幾百個基因,找出這幾百個基因或者找出除了這幾百個基因外其它基因就能夠用這個啦
好比說數據框中有一個分類變量"female","male"。咱們根據這兩個變量,建立一個變量(drink),"female"用來表示喝的飲料("juice"),"male」表示喝的啤酒("beer")
oldvals <- c("female","male") newvals <- factor(c("juice","beer")) # 此處順序一一對應,即female對應juice,male對應beer。因此這一個順序本身仔細點 info$drink <- newvals[match(info$gender,oldvals)] #match將info中gender列元素與oldvals匹配,元素與oldvas中第一個匹配返回1,與第二個匹配返回2。而後其實就是c("juice","beer")[c(1,1,2,2,2,1)]
另外還有一種就是使用向量索引的方式
info$drink[info$gender == "female"] <- "juice" info$drink[info$gender == "male"] <- "beer" info$drink <- factor(info$drink) #還能夠經過|(或)、&(與)操做符,多個條件定義。如咱們如今在性別爲男性、年紀大於等於16的定義爲喝白酒(liquor),將小於等於15的定義爲喝啤酒 info$drink[info$gender == "male" &info$age >= 16] <- "liquor" info$drink[info$gender == "male" & info$age <= 15] <- "beer"
好比咱們如今有一個變量年紀,其中包括3歲到80歲的數據記錄,咱們將年齡小於18歲的定義爲未成年,將大於60歲的定義爲老年,將大於18歲小於60歲的定義爲中年。咱們能夠經過cut函數,先建立邊界值,0到18歲,18到60歲,60歲到無窮大,這三個區間。同時cut函數會將每一個年紀進行匹配,看這個年紀在什麼區間。
cut(x, breaks, labels = NULL, include.lowest = FALSE, right = TRUE, dig.lab = 3, ordered_result = FALSE, ...)
# 由於以前的年齡設置都過小,從新賦值 info$age <- c(13,15,25,35,60,65) info$ageclass <- cut(info$age,breaks = c(0,18,60,Inf),labels = c("teenager","adult","aged")) # 定義年齡區間(0,18],標籤teenager。(18,60],標籤adult。(60,inf],標籤aged。而後一必定位,而後建立標籤變量,即分類變量
單個變量轉換即對數據框中的某一個變量進行公式計算,並從新賦值一個變量,這有三個方法,運用 $ 引用列、使用transform()函數、使用plyr包中的mutate()函數
transform(`_data`, ...)
mutate(.data, ...)
好比說咱們如今他們有一門考試分數,滿分一百的,咱們將它轉化爲滿分150。
info$score <- c(100,98,95,96,99,93) # 添加成績 info$newscore <- info$score * 1.5 # 第一種經過 $ 引用列 info <- transform(info,newscore = score * 1.5) # 經過transform函數轉化 library(plyr) info <- mutate(info,newscore = score * 1.5) # 經過plyr包中的mutate函數轉化
分組轉換就是數據框中有分組變量(一個或多個),而後咱們對各個分組進行統計分析,並將統計結果生成新列看可使用plyr包中的ddply函數。
ddply(.data, .variables, .fun = NULL, ..., .progress = "none", .inform = FALSE, .drop = TRUE, .parallel = FALSE, .paropts = NULL)
舉個例子,好比測脈搏,全部的脈搏數據在一列,有兩個分組變量,性別和有沒有服用某種藥,這樣咱們就能夠統計不一樣性別的脈搏狀況,服用和不服用藥的脈搏狀況,以及不一樣性別在有服用和不用藥狀況下的脈搏狀況。好比咱們要分析男性各自脈搏和全部男性脈搏均數之間的差別,以及女性各自脈搏和全部女性脈搏均數之間的差別。
info$pulse <- c(58,60,59,56,61,63) # 添加脈搏數據 info <- ddply(info,"gender",transform,mpulse = pulse - mean(pulse)) # 首先會根據"gender"將數據分組分紅兩個數據框,而後對兩個數據框調用transform函數,而transform函數定義爲mpulse = pulse - mean(pulse),最後賦值給info
其實這個和上面原理是徹底同樣的,只是應用的函數不一樣而已,以及生成的數據框不一樣。另外這個其實我以爲應該放在統計篇。。
舉例子,統計服藥和不服藥狀況下的,男性和女性脈搏平均數,也就是男性服藥脈搏,男性不服藥脈搏,女性服藥脈搏,女性不服藥脈搏
ddply(info,c("gender","pill"),summarise,mean_pulse = mean(pulse)) # 根據gender(性別)和pill(是否服藥),分組,而後計算各組pulse的平均數,並將該數賦值給變量mean_pulse。ddply返回的是一個數據框
另外還能夠經過aggregate()函數完成分組狀況的統計,以及lapply、apply、tapply等
aggregate(x, by, FUN, ..., simplify = TRUE, drop = TRUE)
因此上面的還能夠用aggregate()
aggregate(info$pulse,by = list(info$gender,info$pill),mean)
split函數能夠將一個數據框根據分組變量轉化爲列表,列表中的元素爲根據變量分組的數據框。有時候分組彙總用起來有點麻煩的時候能夠用這個
dcast(data, formula, fun.aggregate = NULL, ..., margins = NULL, subset = NULL, fill = NULL, drop = TRUE, value.var = guess_value(data))
如下列gcookbook包中的一個名爲plum的數據框爲例
library(reshape2) dcast(plum,length + time ~ survival,value.var = "count")
spread(plum,survival,count)
這個函數貌似比較麻煩一點,目前看到的都是隻有值和可變變量,只有兩個,其它數據會被清除。。
unstack(x, form, ...)
unstack(plum,count ~ length)
而後其它變量被自動清除,試過如下都不行
unstack(plum) unstack(plum,count ~ survival + length +time)
melt(data, id.vars, measure.vars, variable.name = "variable", ..., na.rm = FALSE, value.name = "value", factorsAsStrings = TRUE)
gather(data, key = "key", value = "value", ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)
注意的點:cbind函數合併的數據框的變量長度(行數)要一致,由於是按列綁定。rbind函數合併的數據框變量數(列數)要一致而且列的名稱要相同。
cbind(..., deparse.level = 1) rbind(..., deparse.level = 1)
merge(x, y, by = intersect(names(x), names(y)), by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all, sort = TRUE, suffixes = c(".x",".y"), no.dups = TRUE, incomparables = NULL, ...)
以例子說明,如今有兩批樣本的實驗數據。
截圖中都是隻顯示一小部分,這兩批實驗數據中,樣本有些相同有些不一樣,兩批實驗所用抗體相同。如今咱們來匹配合並兩個數據框中樣本、抗體相同的數據
dplyr包中的inner_join()、left_join()、right_join()、full_join()。他們的用法徹底同樣,只是返回的值稍微有點不一樣
inner_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...)
這些分數爲字符型,如今咱們將它轉化爲數值型,以便後面咱們進行統計
若是咱們直接對整個數據框套用as.numeric,將報錯:(列表)對象不能被強制轉換爲雙精度類型。
看看as.numeric()函數API
能夠看到其中的length參數,意思是:該參數爲非負整數,雙精度值將被強制轉換爲整型,提交的長度參數大於1時將報錯。這個報錯的意思是,只能針對一維向量(矩陣和數組是特殊的向量)強制將元素轉換爲數值型。
數據框的本質是多個向量組合構成,便是多維。。所以,直接對整個數據框應用該函數將報錯,而對其中單列(單個向量)是不會報錯的。
這個時候咱們就能夠運用一些函數,將as.numeric()運用到數據框中單列,好比lapply()
它的意思是lapply()函數返回一個與X(咱們要處理的對象)長度相等的列表,列表中的每一個元素是X中對應元素運用FUN(函數)的結果。