R語言--數據框

建立數據框

由於數據框的本質是由一堆向量或者因子構成的列表,其中的每個向量或者因子表明了一列。所以,數據框能夠包含不一樣類型的數據(數值型、布爾型或字符型),可是每一列的數據類型必須相同。數據庫

data.frame

咱們能夠經過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

能夠經過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()

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()

subset()函數根據條件返回向量或矩陣或數據框

## S3 method for class 'data.frame'
subset(x, subset, select, drop = FALSE, ...)
  • 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 的行

match


固然這是很小的數據,可是,假如咱們手裏有幾千個基因的數據,老闆甩給你幾百個基因,找出這幾百個基因或者找出除了這幾百個基因外其它基因就能夠用這個啦

轉化變量

分類變量轉化爲另外一個分類變量

好比說數據框中有一個分類變量"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, ...)
  • x:待分區的連續數據
  • breaks:邊界值,定義區間
  • labels:各個區間(類別)的結果標籤
  • right:區間閉合的位置,right = TRUE,表示區間右邊閉合,即(18,60]
# 由於以前的年齡設置都過小,從新賦值
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`, ...)
  • _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)
  • x:一個R的對象,要應用公式的數據,即要進行計算的公式。
  • by:一個分組元素列表,其中每一個元素都是x數據框中的變量,也就是用分組變量組合成列表
  • FUN:一個函數,這個函數應用於全部分組子數據框,進行數據統計
  • simplify:邏輯值,表示結果是否簡化爲一個向量或者列表

因此上面的還能夠用aggregate()

aggregate(info$pulse,by = list(info$gender,info$pill),mean)

分組轉換之split

split函數能夠將一個數據框根據分組變量轉化爲列表,列表中的元素爲根據變量分組的數據框。有時候分組彙總用起來有點麻煩的時候能夠用這個

維度轉換

長變寬之dcast

dcast(data, formula, fun.aggregate = NULL, ..., margins = NULL,
  subset = NULL, fill = NULL, drop = TRUE,
  value.var = guess_value(data))
  • data:要變化的數據框
  • formula:變化公式,通常包括標識變量(須要保留的列)和可變變量(轉化生成新列的列),兩個變量之間用 ~ ,~左邊標識標識變量,~右邊標識可變變量
  • value.var:數據列名,即該數值會被填充到新列

如下列gcookbook包中的一個名爲plum的數據框爲例

library(reshape2)
dcast(plum,length + time ~ survival,value.var = "count")

長變寬之spread

spread(plum,survival,count)

長變寬之unstack

這個函數貌似比較麻煩一點,目前看到的都是隻有值和可變變量,只有兩個,其它數據會被清除。。

unstack(x, form, ...)
  • x:待轉換的對象
  • form:一個兩邊的公式,公式左邊是值,右邊是可變變量
unstack(plum,count ~ length)


而後其它變量被自動清除,試過如下都不行

unstack(plum)
unstack(plum,count ~ survival + length +time)

寬變長之melt

melt(data, id.vars, measure.vars,
  variable.name = "variable", ..., na.rm = FALSE, value.name = "value",
  factorsAsStrings = TRUE)
  • data:待轉變的數據框
  • id.vars:標識變量,代表哪些值要聚集到一塊兒。能夠是整數(變量列的下標)或者是字符串(變量的名稱)
  • measure.vars:度量變量,默認是除標識變量之外的全部變量,這些度量變量的名稱會被放到一個叫variable.name列,而它們對應的取值則放到一個名爲value.name的列中

寬變長gather

gather(data, key = "key", value = "value", ..., na.rm = FALSE,
  convert = FALSE, factor_key = FALSE)
  • data:要變化的數據框
  • key:至關於melt函數中的variable.name
  • value:至關於melt函數中的value.name

數據框合併

cbind和rbind

注意的點:cbind函數合併的數據框的變量長度(行數)要一致,由於是按列綁定。rbind函數合併的數據框變量數(列數)要一致而且列的名稱要相同。

cbind(..., deparse.level = 1)
rbind(..., deparse.level = 1)

merge

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, ...)
  • x:數據框x
  • y:數據框y
  • by.x:x中的變量
  • by.y:y中的變量

以例子說明,如今有兩批樣本的實驗數據。


截圖中都是隻顯示一小部分,這兩批實驗數據中,樣本有些相同有些不一樣,兩批實驗所用抗體相同。如今咱們來匹配合並兩個數據框中樣本、抗體相同的數據

dplyr包

dplyr包中的inner_join()、left_join()、right_join()、full_join()。他們的用法徹底同樣,只是返回的值稍微有點不一樣

  • inner_join:返回兩數據框中匹配的值,若是不匹配則不返回。如x有60行,y有60行,按匹配條件,x和y有50行匹配,則顯示這50行匹配合並的數據
  • left_join:返回x數據框中的全部行,以及數據框x和y中的全部列。若是x中的行在y中未匹配,則在新列中該數據爲NA
  • right_join:返回y數據框中的全部行,以及數據框x和y中的全部列。若是y中的行在x中未匹配,則在新列中該數據爲NA
  • full_join:返回x和y的全部行和列。不匹配的各自爲NA
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(函數)的結果。

相關文章
相關標籤/搜索