快速掌握R語言中類SQL數據庫操作技巧

  • 2019 年 10 月 7 日
  • 筆記

在數據分析中,往往會遇到各種複雜的數據處理操作:分組、排序、過濾、轉置、填充、移動、合併、分裂、去重、找重、填充等操作。這時候R語言就是一個很好的選擇:R可以高效地、優雅地解決數據處理操作。(本章節為R語言入門第二部分總結篇:數據操作)

本章內容布局思路:思來想後,想到SQL查詢的查詢思路可以作為本章節的布局思路

  • 1.了解表結構/數據結構
  • 2.對表中的一些數據做出修改、替換、甚至生成新字段
  • 3.from:數據合併/連接
  • 4.where:條件篩選/過濾
  • 5.group:分組
  • 6.having和select:呈現不明顯
  • 7.order:排序
  • 8.其他補充

目錄

1. 初識R語言支持的數據類型

1.1 向量 Vector : c()

1.2 矩陣 Matrix: matrix()

1.3 數據框 DataFrame: data.frame()

1.4 時間序列 XTS: xts()

1.5 因子Factor:factor(補充)

2.查看數據概況

summary()和str()

3.修改/替換/重定義數據

4.數據合併

3.1 向量合併

3.2 cbind列合併(等長)

3.3 rbind行合併

3.4 merge

3.5 補充:集合操作

4.過濾/篩選

4.1 缺失值處理

4.2 數據增減

4.3 數值分段cut

5.分組操作

5.1 aggregate語法

5.2 aggregate分組計算

5.3 aggregate分組計算(formula形式)

6. 排序order

7. 計數table

8. 分裂split

9. 去重與找重unique

10.轉置


1. 初識R語言支持的數據類型

開始之前,需要先了解一下R語言支持的數據類型,以及這些常用類型的特點。以下4種類型是最常用的:向量、矩陣、數據框、時間序列。

可參考↓↓

R語言|第2講:生成數據

R語言快速入門:數據結構+生成數據+數據引用+讀取外部數據

  • 向量 Vector : c()
  • 矩陣 Matrix: matrix()
  • 數據框 DataFrame: data.frame()
  • 時間序列 XTS: xts()
  • 因子Factor:factor(補充)

(圖片來自於粉絲日誌)

1.1 向量 Vector : c()

> x <- c(1:10)  > x   [1]  1  2  3  4  5  6  7  8  9 10

1.2 矩陣 Matrix: matrix()

#矩陣用法  matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,dimnames = NULL) #表示生成1行,1列的一個矩陣,其中僅僅包含一個元素「NA」    #---示例---#  > matrix(c(1,2,3, 11,12,13), nrow = 2, ncol = 3, byrow = TRUE, dimnames = list(c("row1", "row2"), c("C.1", "C.2", "C.3")))       C.1 C.2 C.3  row1   1   2   3  row2  11  12  13  #nrow = 2和ncol = 3 定義2x3的2行3列矩陣  #byrow = TRUE 是控制矩陣中的數據c(1,2,3, 11,12,13)按照行的順序排列,默認按照列排列  #dimnames = list(c("row1", "row2"), c("C.1", "C.2", "C.3")) 定義矩陣行名和列名

1.3 數據框 DataFrame: data.frame()

#其中" <- "是賦值的意思,將向量c(11:15)賦值給對象x  > x <- c(11:15)  > y <- c(1:5)     #將向量x和y合併存儲到數據框中,並重命名為xf和yf  > data.frame(xf = x, yf = y)     xf yf  1  11  1  2  12  2  3  13  3  4  14  4  5  15  5

1.4 時間序列 XTS: xts()

> library(xts)  > x <- c(11:15)  > xts(x,order.by=as.Date('2019-09-14')+1:5)             [,1]  2019-09-15   11  2019-09-16   12  2019-09-17   13  2019-09-18   14  2019-09-19   15

關於xts類型的詳細介紹,請參考文章《可擴展的時間序列xts》http://blog.fens.me/r-xts/

2.查看數據概況
> data(iris)  > head(iris,10)     Sepal.Length Sepal.Width Petal.Length Petal.Width Species  1           5.1         3.5          1.4         0.2  setosa  2           4.9         3.0          1.4         0.2  setosa  3           4.7         3.2          1.3         0.2  setosa  4           4.6         3.1          1.5         0.2  setosa  5           5.0         3.6          1.4         0.2  setosa  6           5.4         3.9          1.7         0.4  setosa  7           4.6         3.4          1.4         0.3  setosa  8           5.0         3.4          1.5         0.2  setosa  9           4.4         2.9          1.4         0.2  setosa  10          4.9         3.1          1.5         0.1  setosa      > summary(iris)    Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species   Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100   setosa    :50   1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300   versicolor:50   Median :5.800   Median :3.000   Median :4.350   Median :1.300   virginica :50   Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199   3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800   Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500      > str(iris)  'data.frame':  150 obs. of  5 variables:   $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...   $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...   $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...   $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...   $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

3.修改/替換/重定義數據

修改指定單元格,修改指定列,within 關聯修改

leadership$age[leadership$age==99] <- NA  leadership$agecat2 <- NA  leadership <- within(leadership,{  agecat2[age>75] <- "Elder"    agecat2[age>=55 & age<=75] <- "Middle Aged"    agecat2[age<55] <- "Young"}  )

4 數據合併

數據操作中,數據(集)合併是經常被用到。例如:合併來源不同,結構相似的兩個表格

3.1 向量合併

#一維向量合併直接將要合併的變量以","分割放到c()中即可。  > x <- c(11:20)  > y <- c(1:10)  > c(x,y)   [1] 11 12 13 14 15 16 17 18 19 20  1  2  3  4  5  6  7  8  9 10

3.2 cbind列合併(等長)

總結:cbind等行數、按列合併(無序)

#生成測試數據  > ID1 <- c(1:4)  > ID2 <- c(2:5)  > name<-c("A","B","C","D")  > score<-c(8,22,7,6)  > student1<-data.frame(ID1,name)  > student2<-data.frame(ID2,score)    #按照行合併student1和student2  > cbind(student1,student2)     ID1 name ID2 score1  1    A   2     82  2    B   3    223  3    C   4     74  4    D   5     6

3.3 rbind行合併

總結:按行合併,需要注意數據集需要有相同的列字段名

> #生成測試數據student1  > ID <- c(1:4)  > score <- c(8,22,7,33)  > student1<-data.frame(ID,score)>    #生成測試數據student2  > ID <- c("A","B","C","D")  > score <- c(11,2,55,3)  > student2<-data.frame(ID,score)    #按行合併,需要注意數據集需要有相同的列字段名  > rbind(student1,student2)  ID score1  1     82  2    223  3     74  4    335  A    116  B     27  C    558  D     3

3.4 merge

#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, ...)  #其中,通過by字段控制連接字段by = "ID"為單字段連接,by = c("ID","NAME",……)為多字段連接;  #通過all=FALSE/TRUE、all.x = TRUE和all.y = TRUE實現內連接、外連接、左連接和右連接
#———merge用法———#  > #生成測試數據  > ID1 <- c(1:4)  > ID2 <- c(2:5)  > name<-c("A","B","C","D")  > score<-c(8,22,7,6)  > student1<-data.frame(ID1,name)  > student2<-data.frame(ID2,score)  >  > #內連接:保留交叉位置數據  > merge(student1,student2,by.x = "ID1", by.y = "ID2",all=TRUE)    ID1 name score  1   1    A    NA  2   2    B     8  3   3    C    22  4   4    D     7  5   5 <NA>     6  > #左連接:保留左邊所有數據及交叉y數據  > merge(student1,student2,by.x = "ID1", by.y = "ID2",all.x=TRUE)    ID1 name score  1   1    A    NA  2   2    B     8  3   3    C    22  4   4    D     7  > #右連接:保留右邊所有數據及交叉x數據  > merge(student1,student2,by.x = "ID1", by.y = "ID2",all.y=TRUE)    ID1 name score  1   2    B     8  2   3    C    22  3   4    D     7  4   5 <NA>     6

3.5 補充:集合操作

集合操作,是對2個向量的操作,處理2個向量之間的數值的關係,找到包含關係、取交集、並集、差集等。、

# 定義2個向量x,y  > x<-c(3:8,NA);x  [1]  3  4  5  6  7  8 NA  > y<-c(NA,6:10,NA);y  [1] NA  6  7  8  9 10 NA    # 判斷x與y重複的元素的位置  > is.element(x, y)  [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE    # 判斷y與x重複的元素的位置  > is.element(y, x)  [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE    # 取並集  > union(x, y)  [1]  3  4  5  6  7  8 NA  9 10    # 取交集  > intersect(x, y)  [1]  6  7  8 NA    # 取x有,y沒有元素  > setdiff(x, y)  [1] 3 4 5    # 取y有,x沒有元素  > setdiff(y, x)  [1]  9 10    # 判斷2個向量是否相等  > setequal(x, y)  [1] FALSE
數據連接主要涉及到merge函數和dplyr包中的*_join等函數,另外sqldf函數(SQL)亦可以實現數據連接功能。

參考→《R語言 數據(集)合併與連接/匹配 | 專題2》

4.過濾/篩選

過濾,是對數據集按照某種規則進行篩選,去掉不符合條件的數據,保留符合條件的數據。對於NA值的操作,主要都集中在了過濾操作和填充操作中,因此就不在單獨介紹NA值的處理了。

可參考↓↓

R語言 | 第一部分:數據預處理 7.數據篩選和8.抽樣

R語言數據管理與dplyr、tidyr | 第4講 5 dplyr中5.1篩選filter和5.3選擇select

R 語言 邏輯運算:TRUE/FALSE | 專題3

4.1 缺失值處理

# 生成數據框  > df<-data.frame(a=c(1,NA,NA,2,NA),  +     b=c('B','A','B','B',NA),  +     c=c(rnorm(2),NA,NA,NA));df     a    b          c  1  1    B -0.3041839  2 NA    A  0.3700188  3 NA    B         NA  4  2    B         NA  5 NA <NA>         NA    # 過濾有NA行的數據  > na.omit(df)    a b          c  1 1 B -0.3041839    # 過濾,保留b列值為B的數據  > df[which(df$b=='B'),]     a b          c  1  1 B -0.3041839  3 NA B         NA  4  2 B         NA

4.2 數據增減

常見如以下不同方法

#方法一:減行數或列數  x=x[,-1] #代表刪除x數據集中第一列數據    #方法二:dplyr::mutate#數值重定義和賦值  #將Ozone列取負數賦值給new,然後Temp列重新計算為(Temp - 32) / 1.8  mutate(airquality, new = -Ozone, Temp = (Temp - 32) / 1.8)    #方法三:subset篩選變量服從某值的子集  subset(airquality, Temp > 80, select = c(Ozone, Temp))

4.3 數值分段

數值分段,就是把一個連續型的數值型數據,按區間分割為因子類型的離散型數據。

> x<-1:10;x   [1]  1  2  3  4  5  6  7  8  9 10    # 把向量轉換為3段因子,分別列出每個值對應因子  > cut(x, 3)   [1] (0.991,4] (0.991,4] (0.991,4] (0.991,4] (4,7]     (4,7]     (4,7]     (7,10]    (7,10]    (7,10]  Levels: (0.991,4] (4,7] (7,10]    # 對因子保留2位精度,並支持排序  > cut(x, 3, dig.lab = 2, ordered = TRUE)   [1] (0.99,4] (0.99,4] (0.99,4] (0.99,4] (4,7]    (4,7]    (4,7]    (7,10]   (7,10]   (7,10]  Levels: (0.99,4] < (4,7] < (7,10]

5 分組操作

此處僅講述aggregate數據分組計算內容,更多分組計算內容

參考→《R語言 分組計算,不止group_by

  • dplyr包中的group_by聯合summarize
  • group_by和summarise單變量分組計算
  • group_by和summarise多變量分組計算
  • ddply分組計算示例

5.1 aggregate語法

aggregate(x, by, FUN)  #x為數據集  #by為分組變量列表  #FUN為計算函數

5.2 aggregate分組計算

> row_names <- rep(c("A","B","C"),3)  > col_names <- LETTERS[1:3]  > df_matrix <- matrix(c(1:27),nrow = 9,dimnames = list(row_names,col_names))  > df_matrix    A  B  C  A 1 10 19  B 2 11 20  C 3 12 21  A 4 13 22  B 5 14 23  C 6 15 24  A 7 16 25  B 8 17 26  C 9 18 27    #注意分組變量為列表形式  > aggregate(df_matrix,list(Group = row_names), mean)    Group A  B  C  1     A 4 13 22  2     B 5 14 23  3     C 6 15 24

5.3 aggregate分組計算補充(formula形式)

可以重點了解一下

aggregate(formula, data, FUN)  #Formulas, one ~ one, one ~ many, many ~ one, and many ~ many:    #一組對一計算變量函數型分組計算:計算變量~分組變量  > aggregate(weight ~ feed, data = chickwts, mean)         feed   weight  1    casein 323.5833  2 horsebean 160.2000  3   linseed 218.7500  4  meatmeal 276.9091  5   soybean 246.4286  6 sunflower 328.9167    #多組對一函數型分組計算:計算變量~分組變量1+分組變量2……  > aggregate(breaks ~ wool + tension, data = warpbreaks, mean)    wool tension   breaks  1    A       L 44.55556  2    B       L 28.22222  3    A       M 24.00000  4    B       M 28.77778  5    A       H 24.55556  6    B       H 18.77778    #一組對多計算變量,函數型分組計算:cbind(計算變量1,計算變量2)~分組變量1  > aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean)    Month    Ozone     Temp  1     5 23.61538 66.73077  2     6 29.44444 78.22222  3     7 59.11538 83.88462  4     8 59.96154 83.96154  5     9 31.44828 76.89655    #多組對多計算變量,函數型分組計算:cbind(計算變量1,計算變量2)~分組變量1+分組變量2……  > aggregate(cbind(ncases, ncontrols) ~ alcgp + tobgp, data = esoph, sum)         alcgp    tobgp ncases ncontrols  1  0-39g/day 0-9g/day      9       261  2      40-79 0-9g/day     34       179  3     80-119 0-9g/day     19        61  4       120+ 0-9g/day     16        24  5  0-39g/day    10-19     10        84  6      40-79    10-19     17        85  7     80-119    10-19     19        49  8       120+    10-19     12        18  9  0-39g/day    20-29      5        42  10     40-79    20-29     15        62  11    80-119    20-29      6        16  12      120+    20-29      7        12  13 0-39g/day      30+      5        28  14     40-79      30+      9        29  15    80-119      30+      7        12  16      120+      30+     10        13

6. 排序

#order默認升序,變量前加「-」代表降序

#排序的操作,大多都是基於索引來完成的

#用order()函數來生成索引,再匹配的數據的數值上面。

可參考↓↓

R語言 排序&去重操作 | 專題1

R語言 | 第一部分:數據預處理

> row_names <- rep(c("A","B","C"),3)  > col_names <- LETTERS[1:3]  > set.seed(1234)  > df_matrix <- matrix(round(rnorm(27,0,1),3),nrow = 9,dimnames = list(NULL,col_names));df_matrix             A      B      C   [1,] -1.207 -0.890 -0.837   [2,]  0.277 -0.477  2.416   [3,]  1.084 -0.998  0.134   [4,] -2.346 -0.776 -0.491   [5,]  0.429  0.064 -0.441   [6,]  0.506  0.959  0.460   [7,] -0.575 -0.110 -0.694   [8,] -0.547 -0.511 -1.448   [9,] -0.564 -0.911  0.575  > df_frame <-   data.frame(group=row_names,df_matrix);df_frame    group      A      B      C  1     A -1.207 -0.890 -0.837  2     B  0.277 -0.477  2.416  3     C  1.084 -0.998  0.134  4     A -2.346 -0.776 -0.491  5     B  0.429  0.064 -0.441  6     C  0.506  0.959  0.460  7     A -0.575 -0.110 -0.694  8     B -0.547 -0.511 -1.448  9     C -0.564 -0.911  0.575  >  > #order,其中默認升序,變量前加「-」代表降序  > #排序的操作,大多都是基於索引來完成的  > #用order()函數來生成索引,再匹配的數據的數值上面。  > df_frame[order(df_frame$A),]    group      A      B      C  4     A -2.346 -0.776 -0.491  1     A -1.207 -0.890 -0.837  7     A -0.575 -0.110 -0.694  9     C -0.564 -0.911  0.575  8     B -0.547 -0.511 -1.448  2     B  0.277 -0.477  2.416  5     B  0.429  0.064 -0.441  6     C  0.506  0.959  0.460  3     C  1.084 -0.998  0.134  > df_frame[order(df_frame$group,-df_frame$A),]    group      A      B      C  7     A -0.575 -0.110 -0.694  1     A -1.207 -0.890 -0.837  4     A -2.346 -0.776 -0.491  5     B  0.429  0.064 -0.441  2     B  0.277 -0.477  2.416  8     B -0.547 -0.511 -1.448  3     C  1.084 -0.998  0.134  6     C  0.506  0.959  0.460  9     C -0.564 -0.911  0.575

7. 計數

計數,是統計同一個值出現的次數。

# 生成20個隨機數的向量  set.seed(1234)  x<-round(rnorm(20)*5);x  # 統計每個值出現的次數  table(x)  hist(x,xlim = c(-10,13),breaks=5)

8 數據分裂

分裂計算,是把一個向量按照一列規則,拆分成多個向量的操作。有時候分裂split也被用於分組計算中。

> row_names <- rep(c("A","B","C"),3)  > col_names <- LETTERS[1:3]  > df_matrix <- matrix(c(1:27),nrow = 9,dimnames = list(NULL,col_names))  > row_names <- rep(c("A","B","C"),3)  > col_names <- LETTERS[1:3]  > df_matrix <- matrix(c(1:27),nrow = 9,dimnames = list(NULL,col_names));df_matrix        A  B  C   [1,] 1 10 19   [2,] 2 11 20   [3,] 3 12 21   [4,] 4 13 22   [5,] 5 14 23   [6,] 6 15 24   [7,] 7 16 25   [8,] 8 17 26   [9,] 9 18 27  > df_frame <-   data.frame(group=row_names,df_matrix);df_frame    group A  B  C  1     A 1 10 19  2     B 2 11 20  3     C 3 12 21  4     A 4 13 22  5     B 5 14 23  6     C 6 15 24  7     A 7 16 25  8     B 8 17 26  9     C 9 18 27  > df_split <- split(df_frame,row_names);df_split  $A    group A  B  C  1     A 1 10 19  4     A 4 13 22  7     A 7 16 25    $B    group A  B  C  2     B 2 11 20  5     B 5 14 23  8     B 8 17 26    $C    group A  B  C  3     C 3 12 21  6     C 6 15 24  9     C 9 18 27

另外,可以用因子類型來控制分裂。分成2步操作,第一步先分成與數據集同樣長度的因子,第二步進行分裂,可以把一個大的向量拆分成多個小的向量。

> # 生成因子規則  > n <- 3; size <- 5  > fat <- factor(round(n * runif(n * size)));fat   [1] 3 3 1 1 0 1 2 1 3 3 1 1 2 2 2  Levels: 0 1 2 3  > # 生成數據向量  > x <- rnorm(n * size);x   [1] -1.2107366 -1.3102467 -0.4083354 -0.5629753  1.2139442  1.6288760 -0.3160227 -1.8076242 -0.6125961  [10] -2.1066644  1.2053009  1.3294407 -0.6836288 -1.7868047  0.1364916  > # 對向量以因子的規則進行拆分  > split(x, fat)  $`0`  [1] 1.213944    $`1`  [1] -0.4083354 -0.5629753  1.6288760 -1.8076242  1.2053009  1.3294407    $`2`  [1] -0.3160227 -0.6836288 -1.7868047  0.1364916    $`3`  [1] -1.2107366 -1.3102467 -0.6125961 -2.1066644

9. 去重與找重

去重,是把向量中重複的元素過濾掉。找重,是把向量中重複的元素找出來。

可參考↓↓

R語言 | 第一部分:數據預處理

R語言 排序&去重操作 | 專題1

R 語言 邏輯運算:TRUE/FALSE | 專題3

> x<-c(3:6,5:8);x  [1] 3 4 5 6 5 6 7 8    # 去掉重複元素  > unique(x)  [1] 3 4 5 6 7 8    # 找到重複元素,索引位置  > duplicated(x)  [1] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE    # 找到重複元素  > x[duplicated(x)]  [1] 5 6
10.轉置

轉置是一個數學名詞,把行和列進行互換,一般用於對矩陣的操作。

# 創建一個3行5列的矩陣  > m<-matrix(1:15,ncol=5);m       [,1] [,2] [,3] [,4] [,5]  [1,]    1    4    7   10   13  [2,]    2    5    8   11   14  [3,]    3    6    9   12   15    # 轉置後,變成5行3列的矩陣  > t(m)       [,1] [,2] [,3]  [1,]    1    2    3  [2,]    4    5    6  [3,]    7    8    9  [4,]   10   11   12  [5,]   13   14   15