Chapter 1 - Basic Introduction



R studio 頁面介紹

  • R studio主要分為四大區塊
  • 1. 左上區為R Script,若想新增編輯頁面可點選左上角的「+」選R Script(windows快捷鍵為ctrl + shift + N , Mac為 command + shift + N)。
  • 2. 左下區R的執行介面(Console),在編輯區塊所執行的指令都會在左下角顯現,也可以在此執行指令。
  • 3. 右上區(Environment)像是倉庫一樣,儲存了匯入及創造出宣告的資料,執行過的命令也會記錄下來。
  • 4. 右下區則包含Files、Plots、Packages、Help、Viewer,可以查看繪製的圖也可以查詢不懂的指令。

1.1 Introduction to R

通常給R 的指令分成兩種,一個 expression,或是一個 assignment。
  • Expression

    • 在R中,每一段指令都是一個expression。

    • 輸入有效的 expression 後,R 會執行並且把結果呈現於 Console 中。

  • Assignment

    • 物件(object)被assign(賦值)後,會出現在Environment中。

    • 物件可以是一個變數、數字、文字、向量、函數或是只是宣告變數類型的空集合,甚至是其他更複雜的形式。

  • Others

    • 在編輯時可以使用「#」來新增註解,該行所有在「#」之後輸入的內容都會在R執行時所略過。

基本數學運算

# 加   ;    減   ;   乘    ;  除    (這些都是Expression)
1 + 3  ; 10 - 8  ; 3 * 2  ; 6 / 3   
## [1] 4
## [1] 2
## [1] 6
## [1] 2
  • 次方、立方、平方根

# 3的平方 ;  3的1/3次方  ; 根號2
3 ^ 2  ;  3 ^ (1/3)  ;  sqrt(2)  
## [1] 9
## [1] 1.44225
## [1] 1.414214
  • log

# 以e為底取log ; # log2代表以2為底
log(65)     ;    log2(10)
## [1] 4.174387
## [1] 3.321928
  • 特殊字元 \(\pi ; e\)

pi  ;  exp(1)
## [1] 3.141593
## [1] 2.718282
  • 小數位數取捨

# 四捨五入  ;   # 四捨五入到小數點第二位  ;   # 無條件捨去  ;  # 無條件進位  ;  # 取絕對值
round(4.7)  ;  round(4.786, 2)  ;  floor(4.7)  ;  ceiling(4.7)  ;  abs(-4.7)         
## [1] 5
## [1] 4.79
## [1] 4
## [1] 5
## [1] 4.7

基本統計量

x <- c( 1 , 2 , 3 , 4 )    # 也可以寫成 x <- 1:4 (這個就是assignment)
# 總和     # 平均數     # 中位數      # 變異數    # 樣本標準差
sum(x)  ;  mean(x)  ;  median(x)   ;   var(x)   ;    sd(x)     ; summary(x)    
## [1] 10
## [1] 2.5
## [1] 2.5
## [1] 1.666667
## [1] 1.290994
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00    1.75    2.50    2.50    3.25    4.00
cumsum(x)     # 累加
## [1]  1  3  6 10
cumprod(x)    # 累乘(可以算階乘)
## [1]  1  2  6 24

Chapter 2 - R的物件


        看資料結構、類別、屬性

#結構      
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 ...
#類別
class(iris)
## [1] "data.frame"
#屬性
attributes(iris)
## $names
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width" 
## [5] "Species"     
## 
## $class
## [1] "data.frame"
## 
## $row.names
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
##  [18]  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34
##  [35]  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51
##  [52]  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68
##  [69]  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85
##  [86]  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102
## [103] 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
## [120] 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
## [137] 137 138 139 140 141 142 143 144 145 146 147 148 149 150

向量(c( ) ; concatenate)

數值向量(numeric vector)

  • eg. 1,2,3
class(c(7,8,9))
## [1] "numeric"

字串向量(character vector)

class(c("葉哥好師","嗨嗨"))
## [1] "character"

布林向量(logical vector)

class(c(TRUE,FALSE))
## [1] "logical"

向量的運算

  • 向量+向量

    • 在 R 中,大部份的運算都是向量式的。
    • 當多組向量在進行運算時,會由相對應位置的元素進行運算。
    • 當相加的兩個向量長度不同時,R會自動重複比較短的向量,補到和較長的向量相同的長度,然後用 一樣的方式去做計算。
c(1,2,3)+c(1:3)
## [1] 2 4 6
2+c(1,2,3)  
## [1] 3 4 5
c(1,2)+c(1,2,3,4)  
## [1] 2 4 4 6
c(1,3)+c(1,2,3)
## Warning in c(1, 3) + c(1, 2, 3): 較長的物件長度並非較短物件長度的倍數
## [1] 2 5 4
x <- c(1,2,3) ; y <- c(3,6,9)
x+y  ;  x*y  ;  y/x
## [1]  4  8 12
## [1]  3 12 27
## [1] 3 3 3

矩陣(Matrix)

  • Matrix如同線性代數中學的,有列有行,存放一定是數值(numeric)

  • Matrix可以由一長串的向量去轉換而成,告訴他維度即可

## 1 ~ 12的打法可以打 : 
## == 是用來判斷有沒有相等
1:12
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12
(x1 = matrix(1 : 12 ,ncol = 6) )
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    3    5    7    9   11
## [2,]    2    4    6    8   10   12
(x2 = matrix(1 : 12 ,ncol = 6, byrow = T) )
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    2    3    4    5    6
## [2,]    7    8    9   10   11   12
(y1 = matrix(1 : 4 ,nrow = 2) )
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
(y2 = matrix(1 : 4 ,nrow = 2, byrow = T) )
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4

轉置矩陣 與 反矩陣

t(x1) # 轉置(transpose)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
## [3,]    5    6
## [4,]    7    8
## [5,]    9   10
## [6,]   11   12
solve(y1)
##      [,1] [,2]
## [1,]   -2  1.5
## [2,]    1 -0.5

矩陣乘法 與 對應元素相乘

x1
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    3    5    7    9   11
## [2,]    2    4    6    8   10   12
t(x1) %*% x1
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    5   11   17   23   29   35
## [2,]   11   25   39   53   67   81
## [3,]   17   39   61   83  105  127
## [4,]   23   53   83  113  143  173
## [5,]   29   67  105  143  181  219
## [6,]   35   81  127  173  219  265
x1 * x1   # t(x1) * x1 不能跑,因為兩個物件維度不一樣
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    9   25   49   81  121
## [2,]    4   16   36   64  100  144

Data Frame

  • Data.frame內存放一大堆變數(行向量), 變數間型態可以不同

  • 限制:變數間長度必須一樣

  • 最常使用的物件形式(相當於SAS的Dataset)

data <- data.frame(x1=c(1,2,3), #若要換行則此逗號要擺這
                   x2=c('a','b','c'))
data  ;  class(data)
##   x1 x2
## 1  1  a
## 2  2  b
## 3  3  c
## [1] "data.frame"
data <- data.frame(x1=c(1,2,3,4), 
                   x2=c('a','b','c'))
## Error in data.frame(x1 = c(1, 2, 3, 4), x2 = c("a", "b", "c")) : 
  arguments imply differing number of rows: 4, 3

List

  • 彈性較大的物件,想像成一種Data.frame,但允許變數長度不同

  • Data.frame 為 List 的一種特例 : 長度相同

lst <- list(A=c(1:5),
            B=c('a','b'))
lst
## $A
## [1] 1 2 3 4 5
## 
## $B
## [1] "a" "b"


  • Dataframe取值

    • 利用[i,j] 來對 dataframe 進行取值的動作,其中, i 為列數、 j 為行數

    • [i,] 表示取出 dataframe 中第 i 列的所有資料,包含所有行變數

    • [,j] 表示取出 dataframe 中第 j 行的所有資料,包含所有列資料

    • $ (錢字號)這裡可以用來挑選特定欄位!記得搭配tab鍵讓你事半功倍!

## Data.frame
data <- data.frame(Date=c('7/23','7/23'),
                   Come=c(T,F),
                   Time=c(3,6))
data
##   Date  Come Time
## 1 7/23  TRUE    3
## 2 7/23 FALSE    6
## 好,我要從data中取出日期的變數(欄位、向量、抽屜)
data$Date ; data[,1]
## [1] 7/23 7/23
## Levels: 7/23
## [1] 7/23 7/23
## Levels: 7/23
## 好,我要從data中取出是否會來的變數(欄位、向量、抽屜)
data$Come ; data[,2]
## [1]  TRUE FALSE
## [1]  TRUE FALSE
## 好,我要從data中取出 '6'
data[2,3]
## [1] 6
  • List取值

    • [i]:取出 list 中的第 i 個物件,注意!取出來的物件依舊是 list 結構!

    • [[i]]:取出第 i 個物件中的全部元素,注意![[]]會破壞原本的 list 結構!

    • [[i]][j]:取出第 i 個物件中的第j個元素

    • 若物件已命名,可以利用 $ (錢字號)來提取物件

## List
data <- list(Date=c('7/23','7/24','7/25','7/26'),
             Come=c(T,F),
             Time=c(3,6))
data
## $Date
## [1] "7/23" "7/24" "7/25" "7/26"
## 
## $Come
## [1]  TRUE FALSE
## 
## $Time
## [1] 3 6
## 好,我要從data中取出日期的變數(欄位、向量、抽屜)
## 只是今天衣櫃的每個抽屜長度可以不一樣
data$Date
## [1] "7/23" "7/24" "7/25" "7/26"
data[1]  # 仍然是list格式
## $Date
## [1] "7/23" "7/24" "7/25" "7/26"
data[[1]]
## [1] "7/23" "7/24" "7/25" "7/26"
data[[1]][2]
## [1] "7/24"

特別的物件

  • NA(Not Avaliable)

    • 未來資料中一定常常碰到NA

## NA常常就像這樣任性的存在
x <- c(1,2,3,NA,5)
y <- c(1,2,NA,4,5)
## NA只要碰到加減乘除就會無效
x + y 
## [1]  2  4 NA NA 10
mean(x) 
## [1] NA
## 只要把缺憾移除掉人生就美好多了
mean(x,na.rm=T) 
## [1] 2.75
## 通常NA有規則可以填補我們就會補起來
x[4] <- 4
## 但往往你需要更聰明的方式去補而不是這樣傻傻的數啊 !!
## is.na可以回傳變數哪一個位置為NA
is.na(y)
## [1] FALSE FALSE  TRUE FALSE FALSE
y[ is.na(y) ] <- 3
  • Inf

my.money <- c(0,100,Inf) ; your.money <- c(-Inf,10,0)
my.money+your.money
## [1] -Inf  110  Inf
my.money/your.money ## 我也不知道為什麼 Inf/0會=Inf,可能要問問助教
## [1]   0  10 Inf
  • NaN(Not a Number)

0/0 ; 1/0-1/0
## [1] NaN
## [1] NaN

Chapter3 - 常用的技巧


        a. 看部分資料

head(iris,3)  # 預設為看前六行
##   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
tail(iris,3)
##     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
## 148          6.5         3.0          5.2         2.0 virginica
## 149          6.2         3.4          5.4         2.3 virginica
## 150          5.9         3.0          5.1         1.8 virginica

        b. 擷取部分資料

data = iris[1:6, 1:5]
data ; class(data)
##   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
## [1] "data.frame"

        c. 改資料欄位名字

names(data)  #看現在欄位的名字
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width" 
## [5] "Species"
names(data) = c('花萼長', '花萼寬', '花瓣長', '花瓣寬', '品種')
names(data)
## [1] "花萼長" "花萼寬" "花瓣長" "花瓣寬" "品種"

        d. 新增欄列、刪除欄列

# 刪除第五欄
data[,-5]
##   花萼長 花萼寬 花瓣長 花瓣寬
## 1    5.1    3.5    1.4    0.2
## 2    4.9    3.0    1.4    0.2
## 3    4.7    3.2    1.3    0.2
## 4    4.6    3.1    1.5    0.2
## 5    5.0    3.6    1.4    0.2
## 6    5.4    3.9    1.7    0.4
new = c('a','b','c','d','e','f')
cbind(data, new)  # 增加第六欄
##   花萼長 花萼寬 花瓣長 花瓣寬   品種 new
## 1    5.1    3.5    1.4    0.2 setosa   a
## 2    4.9    3.0    1.4    0.2 setosa   b
## 3    4.7    3.2    1.3    0.2 setosa   c
## 4    4.6    3.1    1.5    0.2 setosa   d
## 5    5.0    3.6    1.4    0.2 setosa   e
## 6    5.4    3.9    1.7    0.4 setosa   f
# 刪除第六列
data[-6,]
##   花萼長 花萼寬 花瓣長 花瓣寬   品種
## 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
new = c(5.2 , 3.1, 1.1, 0.3, 'setosa')
rbind(data, new)  # 增加第七列
##   花萼長 花萼寬 花瓣長 花瓣寬   品種
## 1    5.1    3.5    1.4    0.2 setosa
## 2    4.9      3    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    3.6    1.4    0.2 setosa
## 6    5.4    3.9    1.7    0.4 setosa
## 7    5.2    3.1    1.1    0.3 setosa























        e. 看資料維度 與 資料結構

dim(data)
## [1] 6 5
str(data)  # attributes(data)
## 'data.frame':    6 obs. of  5 variables:
##  $ 花萼長: num  5.1 4.9 4.7 4.6 5 5.4
##  $ 花萼寬: num  3.5 3 3.2 3.1 3.6 3.9
##  $ 花瓣長: num  1.4 1.4 1.3 1.5 1.4 1.7
##  $ 花瓣寬: num  0.2 0.2 0.2 0.2 0.2 0.4
##  $ 品種  : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1

        f. 更改某一欄

data$品種 = '某一種花'
data
##   花萼長 花萼寬 花瓣長 花瓣寬     品種
## 1    5.1    3.5    1.4    0.2 某一種花
## 2    4.9    3.0    1.4    0.2 某一種花
## 3    4.7    3.2    1.3    0.2 某一種花
## 4    4.6    3.1    1.5    0.2 某一種花
## 5    5.0    3.6    1.4    0.2 某一種花
## 6    5.4    3.9    1.7    0.4 某一種花

        g. 選取特定的資料(列)

## 選擇 花萼長 >= 5 的資料(列)
(index = data$花萼長 >= 5)
## [1]  TRUE FALSE FALSE FALSE  TRUE  TRUE
data[index,]
##   花萼長 花萼寬 花瓣長 花瓣寬     品種
## 1    5.1    3.5    1.4    0.2 某一種花
## 5    5.0    3.6    1.4    0.2 某一種花
## 6    5.4    3.9    1.7    0.4 某一種花

練習

  • 1. matrix 的製作與運算

    • 大家都知道回歸分析中估計係數常使用最小平方法,公式為\((X^{'}X)^{-1}X^{'}Y\),如果已知\(X\)\(Y\)分別是下面這兩個,請使用R套入公式計算出答案

X  ;  Y  #請宣告兩個變量X、Y,分別代表下面的X矩陣和Y矩陣
##      [,1] [,2]
## [1,]    1    1
## [2,]    0    2
## [3,]    1    0
##      [,1]
## [1,]   13
## [2,]   -2
## [3,]    1

  • 2. data frame 製作與運用

    • 你能將左邊資料變成右邊資料嗎?









  • 3. list 製作與運用

    • 你能將左邊資料變成右邊資料嗎?















   






Chapter4 - 常用的function


1. ?in R

  • 忘記一個function的用法時常常用?來查詢

    • 或是用help()

?mean
??mean
help(mean)

2. length

  • 看一個向量長度時常用length

length(c(1:10))
## [1] 10

3. sort, order, rank

  • sort:將向量元素從小排到大

  • order:再以從小排到大的結果下,「排名結果」依序對應至原本向量中的第幾個「位置」

  • rank : 由小到大排列的情況下,每個元素依序「排名」第幾

set.seed(10)
(x <- sample(10, 7))
## [1] 6 3 4 5 1 2 7
sort(x)
## [1] 1 2 3 4 5 6 7

y <- sort(x)
order(x)
## [1] 5 6 2 3 4 1 7
rank(x)
## [1] 6 3 4 5 1 2 7
x[order(x)]
## [1] 1 2 3 4 5 6 7
y
## [1] 1 2 3 4 5 6 7
y[rank(x)]
## [1] 6 3 4 5 1 2 7
x
## [1] 6 3 4 5 1 2 7

4. seq, rep

  • seq 可以想成產生一連串有規律的數字(ex:等差數列)

    ?seq ==> seq(from = 1, to = 1, …)

  • rep 可以想成產生一連串有重複的數字

    ?rep ==> rep(x, … )

  • 常常seq跟rep會一起搭配

seq(from = 1, to = 9, by = 2) ## seq(1,9,2)
## [1] 1 3 5 7 9
seq(from = 9, to = 1, by = -2) ## seq(9,1,-2)
## [1] 9 7 5 3 1
rep( seq(from = 1, to = 9, by = 2) , times= 2)
##  [1] 1 3 5 7 9 1 3 5 7 9
rep( seq(from = 1, to = 9, by = 2) , each= 2)
##  [1] 1 1 3 3 5 5 7 7 9 9
rep(seq(from = 1, to = 9, by = 2) , each = 3 , times = 2)
##  [1] 1 1 1 3 3 3 5 5 5 7 7 7 9 9 9 1 1 1 3 3 3 5 5 5 7 7 7 9 9 9

5. 邏輯判斷

  • 以下介紹常用的邏輯判斷符號

    • <> : 小於、大於。

    • <=>= : 小於等於、大於等於。

    • == : 等於。

    • != : 不等於。

    • & : 交集(且)。

    • | : 聯集(或)。

    • A %in% B : A是否在B內。

3 > 2 ; 3 < 2
## [1] TRUE
## [1] FALSE
3 >= 5 ; 3 <= 5
## [1] FALSE
## [1] TRUE
# 你可以key 2 = 3  看看
2 == 3  ; 2 != 3
## [1] FALSE
## [1] TRUE

data
##   花萼長 花萼寬 花瓣長 花瓣寬     品種
## 1    5.1    3.5    1.4    0.2 某一種花
## 2    4.9    3.0    1.4    0.2 某一種花
## 3    4.7    3.2    1.3    0.2 某一種花
## 4    4.6    3.1    1.5    0.2 某一種花
## 5    5.0    3.6    1.4    0.2 某一種花
## 6    5.4    3.9    1.7    0.4 某一種花
data$花瓣長 < 5 & data$花瓣長 > 4.6    # 知道true and false 就可以抓出特定資料
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
data$花瓣長 > 5 & data$花瓣寬 == 0.2
## [1] FALSE FALSE FALSE FALSE FALSE FALSE

## 看物件是否有包含在裡面
c(2,5) %in% c(1:3)
## [1]  TRUE FALSE

if else

  • ifelse簡易語法

    • ifelse(條件式, A(TRUE) , B(FALSE) )

      如果條件式判斷為TRUE,則為A
      如果條件式判斷為FALSE,則為B
ifelse( 3 > 2 , 3 + 2 , 3 - 2 ) #如果3>2成立,則執行3+2,否則執行3-2
## [1] 5
  • 條件執行

    • if   ( A條件式 ){

            A條件式判斷為TRUE,則執行此區塊
      }else if   ( B條件式 ){
            A條件式判斷為FALSE,且B條件式判斷為TRUE,則執行此區塊
      }else{
             A條件式和B條件式皆判斷為FALSE,則執行此區塊}
if(3 < 2){
  3 + 2               # 如果 "3 < 2" 為TRUE,則執行3 + 2
}else if (3 == 2){
  3 * 2               # 否則如果 "3 == 2" 為TRUE,則執行3 * 2
}else{               
  3 - 2               # 如果 "3 < 2"和 "3 == 2" 皆為FALSE,則執行3 - 2
}
## [1] 1

迴圈結構

擁 有 了 他 , 就 擁 有 了 半 個 世 界
  • for迴圈

    for(variable in iterator) {Expressions}

    variable : 宣告一個變量

    iterator : 疊代器,用來宣告遞迴過程中變量要依序變換的值,

    也就宣告一個遞迴用的「向量」Expressions : 可以跟variable有關或無關的運算

x <- 0
for(i in 1:5){
  x <- x + i
  print(x)
}
## [1] 1
## [1] 3
## [1] 6
## [1] 10
## [1] 15
x
## [1] 15

6. which

  • which是一個很常用的function

    which可以理解為:哪一個為TURE

    which更常拿來挑選資料

which(c('a', 'b', 'c') == 'b')
## [1] 2
set.seed(1)
(x = rnorm(20))
##  [1] -0.62645381  0.18364332 -0.83562861  1.59528080  0.32950777
##  [6] -0.82046838  0.48742905  0.73832471  0.57578135 -0.30538839
## [11]  1.51178117  0.38984324 -0.62124058 -2.21469989  1.12493092
## [16] -0.04493361 -0.01619026  0.94383621  0.82122120  0.59390132
which(x > 1)   # 誰大於1
## [1]  4 11 15
sum(x > 1)     # 有多少筆大於1
## [1] 3
x[x>1]         # 挑出大於1的
## [1] 1.595281 1.511781 1.124931

7. 自定function

  • 有時候我們會需要自定一個function來完成某些事情

    這邊教大家如何寫一個自己的function

    假設我們沒有計算算平均數的function,我們要自己寫一個

cust.mean <- function(x){
  mean.result <- sum(x)/length(x)
  return(mean.result)
}

cust.mean(1:10)
## [1] 5.5
## It's same
mean(1:10)
## [1] 5.5

8. 字串處理:nchar(長度), substr(擷取), paste(剪貼), strsplit(分割)

  • 字串常常是很棘手的難題

    例如:台北市文山區指南路三段….

    也許我們想保留的只有台北市文山區或是指南路三段

    這時候就會對字串做些處理

x <- c('ABC-88','WTF-978','CBD-0857')
## 計算字數
nchar(x)
## [1] 6 7 8
## 切割英文跟數字
strsplit(x, split = '-')
## [[1]]
## [1] "ABC" "88" 
## 
## [[2]]
## [1] "WTF" "978"
## 
## [[3]]
## [1] "CBD"  "0857"
## 字串的擷取
substr(x = x[1] , start = 1 , stop = 5)
## [1] "ABC-8"
## 字串的剪貼 
paste(substr(x[2],1,7),substr(x[3],5,7), sep = '-')
## [1] "WTF-978-085"

9. 變數種類的轉換

有時候資料並非為我們預想中的資料型態,因此我們需要做轉換

  • as.character

    • 轉成character型態

x <- c(1,2,3)
as.character(x)
## [1] "1" "2" "3"
  • as.numeric

    • 轉成numeric型態

    • 若轉換過去沒有對應到數字則會出現NA

    • 注意factor ==> numeric

x <- c('1','2')
as.numeric(x)
## [1] 1 2
y <- c('1','a')
as.numeric(y)
## Warning: 強制變更過程中產生了 NA
## [1]  1 NA
z <- factor(c('a','b','c'))
as.numeric(z)
## [1] 1 2 3
z1 <- factor(c('a','b','c'),levels=c('c','b','a'))
as.numeric(z1)
## [1] 3 2 1
w <- factor(c('4','5','6'))
as.numeric(w)
## [1] 1 2 3
        注意:若是要由factor轉為numeric,須先轉成character再轉成numeric
w <- factor(c('4','5','6'))
as.numeric( as.character(w) )
## [1] 4 5 6
  • as.factor

x <- c(1,2,3)
as.factor(x)
## [1] 1 2 3
## Levels: 1 2 3
y <- c('a','b','c')
as.factor(y)
## [1] a b c
## Levels: a b c

Chapter 5 - 資料處理分析

設定R工作環境

  • 查詢工作目錄 (get working directory)

    • getwd:看目前工作目錄在哪裡

getwd()
## [1] "/Users/chenchunyen/Documents/Projects/R工作坊教材"
  • 設定工作目錄 (set working directory)

    • setwd:直接手動設定工作目錄

# Windows
setwd("C:\\Users")

# Mac
setwd("/Users/chenchunyen/Desktop/")

讀取資料

  • csv file

    • write.csv:匯出csv檔

    • read.csv:讀入csv檔

demo <- iris 

# 直接將demo.csv存至剛剛設定的工作目錄
write.csv(demo,"demo.csv")

# 將demo.csv存至指定路徑
write.csv(demo,"/Users/chenchunyen/Desktop/Code/Program/Workshop/demo.csv")
# 將剛剛匯出的demo.csv檔讀進來
data <- read.csv("/Users/chenchunyen/Desktop/Code/Program/Workshop/demo.csv")
   # or
data <- read.csv(file.choose())
  • read.table

    • sep:行與行之間以什麼做分割(csv為以 , 做區隔)

data <- read.table("/Users/chenchunyen/Desktop/Code/Program/Workshop/demo.csv",header = T,sep = ',')
  • scan

    • 連續輸入數字,按一次enter鍵可以輸入下一筆數字,連按兩次enter將結束輸入。

s <- scan()
> s <- scan()
1: 5
2: 4
3: 0
4: 0
5: 
Read 4 items

> s
[1] 5 4 0 0
  • 文字編碼問題

    • Mac-utf8 讀取 windows-big5編碼

data <- read.csv("demo.csv",fileEncoding = 'big5')
  • windows-big5 讀取 Mac-utf8 編碼

data <- read.csv("demo.csv",fileEncoding = 'utf8')

Chapter 6 - 畫圖


掌 握 視 覺 化 , 你 就 是 半 個 資 料 科 學 家

基本繪圖技巧

par(mfrow = c(2,2))   # 將頁面切成四等份
x = rnorm(50)
plot(x)
boxplot(x)
hist(x)  # x 軸當成連續
barplot(x)  # x 軸當成類別









par(mfrow = c(2,2))   
par(family="STKaiti")   #顯示中文(可換各種字型)
plot(x, main = 'plot 指令可以放兩個維度')
boxplot(x, ylim = c(-3,3))
hist(x, xlab = '我是x軸', ylab = '我是y軸', breaks = seq(-4, 4, 0.05), prob = T); lines(density(x, width = 1))

barplot(x, col =2)  

進階技巧

plot(1:10, rep(1, 10), pch=20, col=1:10, cex=5, xlab="", ylab="") 
text(1:10, rep(1.2, 10), labels=1:10)




plot(iris[,1], iris[,2], pch = 16 ,col = 
       ifelse(iris[,5] == 'setosa', 'red', 
              ifelse(iris[,5] == 'versicolor', 'blue', 'green')) )


par(family = 'STKaiti')
x = iris[,1] ; y = iris[,2]
plot(y~x, xlim=c(1.5,9), ylim=c(1.5,9), type="n", main = '迴歸直線')
points(x[1:50], y[1:50], col="red")
points(x[51:100], y[51:100], col="blue")
points(x[101:150], y[101:150], col="green") 
abline(lm(y~x)) # 增加線


pairs(iris[,1:4], col=as.integer(iris[,5])+1, panel=panel.smooth)


library(scatterplot3d)
z <- seq(-10, 10, 0.01)
x <- cos(z)
y <- sin(z)
scatterplot3d(x, y, z, highlight.3d=TRUE, col.axis="blue",
   col.grid="lightblue", main="scatterplot3d - 1", pch=20)


Chapter 7 - 套件


dplyr

  • 實用工具 dplyr

    • dplyr是資料的整理、資料彙整的好幫手

    • 可以幫你省去許多時間,只要你對他夠熟悉!

    • 接下來跟各位介紹一些基本的函式

# 安裝套件
install.packages('dplyr')
# 載入套件
library(dplyr) #注意,重新開啟R之後,要再使用dplyr套件的話,都要再重新載入套件:library(dplyr)
  • 請先下載此資料

  • a. select

    • 挑選欄位

      Ex : 從資料中挑選(or剔除)我們要練習的欄位

# 挑選資料欄位
temp <- select(data, 鄉鎮市區, 交易標的)
# 剔除資料欄位
temp <- select(data, -鄉鎮市區)
# 挑我們練習的欄位
data.new <- select(data,-c(非都市土地使用分區, 非都市土地使用編定, 交易筆棟數,
                           移轉層次, 建物現況格局.房:建物現況格局.隔間,
                           車位類別, 備註, 編號))
  # or
data.new <- select(data,-c(6,7,9,10,17:20,24,27,28))
  • b. filter

    • 按照某些條件挑選資料列

      Ex : 我們想要看文山區的房屋交易

data.wenshan <- filter(data.new, 鄉鎮市區=='文山區')
head(data.wenshan)
  • c. mutate

    • 修改欄位、新增欄位

      Ex1 : 建物(以及土地)移轉總面積平方公尺 轉換成 建物(土地)坪數 (1平方公尺 = 0.3025 坪)

data.new <- mutate(data.new,建物坪數=建物移轉總面積平方公尺*0.3025,
                   土地坪數=土地移轉總面積平方公尺*0.3025)

                      Ex2 : 簡單計算坪價:總價元/建物坪數

# 注意建物坪數=0 算出來會是Inf
mutate(data.new,坪價=總價元/建物坪數)
# 避開建物坪數=0
data.new <- mutate(data.new, 坪價=ifelse(建物坪數==0, 0, 總價元/建物坪數))
  • d. arrange

    • 排序:遞增、遞減

    • desc : 遞減,用在arrange函式

Ex : 想按照坪價排序,由低到高、由高到低

arrange(data.new,坪價)
arrange(data.new,desc(坪價))
  • e. summarise

    • 做資料彙總的函式,可以擺放不同的彙總方式。

    • Ex : 計算筆數、計算平均、最大值…

    • 通常配合group_by

# ?mean 有NA時去計算平均數會得到NA的結果
# na.rm幫助我們把na去除掉!
summarise(data.new,
          平均坪價 = mean(坪價,na.rm = T))
##   平均坪價
## 1 523112.5
# 也可以一次計算多個彙總函式
summarise(data.new,
          平均坪價 = mean(坪價,na.rm = T),
          坪價中位數 = median(坪價,na.rm = T),
          最貴 = max(坪價,na.rm = T),
          最便宜 = min(坪價,na.rm = T))
##   平均坪價 坪價中位數      最貴 最便宜
## 1 523112.5   479432.1 165289256      0
  • f. group_by

    • group_by可以想像成把指定的欄位中值相同的資料偷偷綁在一塊(從資料上看不出改變)

    • group_by(data.new,鄉鎮市區) ==> 把文山區的資料綁一起、松山區的資料綁一起…

    • 通常一定會配合其他dplyr的函式, Ex: filter, mutate, summarise ….

Ex : 想要知道台北市各行政區的平均坪價、坪價中位數、最貴、最便宜

result <- summarise(group_by(data.new,鄉鎮市區),
                    平均坪價 = mean(坪價,na.rm = T),
                    坪價中位數 = median(坪價,na.rm = T),
                    最貴 = max(坪價,na.rm = T),
                    最便宜 = min(坪價,na.rm = T))

# 發現鄉鎮市區欄位中有很多的異常值,要把它去除
# 動動腦思考看看要怎麼去除
result$鄉鎮市區 <- as.character(result$鄉鎮市區)
result <- filter(result,nchar(result$鄉鎮市區)==3)

Ex : 想要知道台北市各行政區的房屋交易筆數

# 計算筆數有蠻多種方式: n(), length(), tally
summarise(group_by(data.new,鄉鎮市區),
          交易筆數a=n(),
          交易筆數b=length(建物坪數),
          交易筆數c=length(坪價))
## # A tibble: 12 x 4
##    鄉鎮市區 交易筆數a 交易筆數b 交易筆數c
##    <fct>        <int>     <int>     <int>
##  1 北投區         842       842       842
##  2 大安區         455       455       455
##  3 大同區         192       192       192
##  4 南港區         222       222       222
##  5 內湖區         531       531       531
##  6 士林區         435       435       435
##  7 松山區         292       292       292
##  8 萬華區         416       416       416
##  9 文山區         451       451       451
## 10 信義區         315       315       315
## 11 中山區         611       611       611
## 12 中正區         227       227       227
tally(group_by(data.new,鄉鎮市區))
## # A tibble: 12 x 2
##    鄉鎮市區     n
##    <fct>    <int>
##  1 北投區     842
##  2 大安區     455
##  3 大同區     192
##  4 南港區     222
##  5 內湖區     531
##  6 士林區     435
##  7 松山區     292
##  8 萬華區     416
##  9 文山區     451
## 10 信義區     315
## 11 中山區     611
## 12 中正區     227

ggplot

  • ggplot : 資料視覺化好幫手


挑 戰 你 的 創 意 - 客 製 化 的 好 幫 手

  • ggplot的基本架構

    • 資料 (data) 和映射 (mapping)

    • 幾何對象 (geometric)

    • 座標尺度 (scale)

    • 統計轉換 (statistics)

    • 座標系統 (coordinante)

    • 圖層 (layer)

    • 刻面 (facet)

    • 主題 (theme)

ggplot(data=…, aes(x=…, y=…)) +

geom_xxx(…) + stat_xxx(…) + facet_xxx(…) + …

library(dplyr)
library(ggplot2)
stw <- starwars %>% filter(gender == 'male' | gender == 'female') %>% 
  group_by(gender,eye_color) %>% summarise(amount = n()) %>% 
  mutate(rate = round(amount/sum(amount),2) )
stw %>% 
  ggplot(aes(x = gender ,y = rate ,fill = eye_color)) +
  geom_bar(stat = 'identity', position = 'stack')+ # stack為類別堆疊
  theme(text=element_text(size = 15, family = "STHeiti")) 

library(dplyr)
library(ggplot2)
d <- iris        # Full data set
d_bg <- d[, -5]  # Background Data - full without the 5th column (Species)

x2 = ggplot(d, aes(x = Sepal.Width, fill = Species)) + #設定x軸,用種類當
  geom_histogram(data = d_bg, fill = "grey", alpha = .5) +
  geom_histogram(colour = "black") +
  facet_wrap(~ Species) +
  guides(fill = FALSE) +  # to remove the legend
  theme_bw()              # for clean look overall
x2
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

mtcars$car = row.names(mtcars)
p = ggplot(mtcars, aes(x=car, y=mpg, fill=mpg)) +
  geom_bar(stat='identity') +theme_light() +
  scale_fill_gradient(low='red', high='white', limits=c(5,40)) +
  theme(axis.title.y=element_text(angle=0))
# p + theme(axis.text.x = element_text(angle=45, vjust = 1, hjust=1))
x3 = p + coord_polar()
x3


rlist

  • list界的dplyr

    • 相對於data.frame,list是較難處理的資料型態

    • rlist提供許多和dplyr相同的函式,可以提高處理list的效率

    • 接下來跟各位介紹一些基本的函式

      #### 範例資料
library(rlist)
library(dplyr)
jsontext <- '[
  {        "Name" : "Ken",
           "Age" : 24,
           "Interests" : [
           "reading",
           "music",
           "movies"
           ],
           "Expertise" : {
           "R": 2,
           "CSharp": 4,
           "Python" : 3
           }
           },
           {
           "Name" : "James",
           "Age" : 25,
           "Interests" : [
           "sports",
           "music"
           ],
           "Expertise" : {
           "R" : 3,
           "Java" : 2,
           "Cpp" : 5
           }
           },
           {
           "Name" : "Penny",
           "Age" : 24,
           "Interests" : [
           "movies",
           "reading"
           ],
           "Expertise" : {
           "R" : 1,
           "Cpp" : 4,
           "Python" : 2
           }
           }
           ]'
people <- list.parse(jsontext, "json")
str(people)
## List of 3
##  $ :List of 4
##   ..$ Name     : chr "Ken"
##   ..$ Age      : int 24
##   ..$ Interests:List of 3
##   .. ..$ : chr "reading"
##   .. ..$ : chr "music"
##   .. ..$ : chr "movies"
##   ..$ Expertise:List of 3
##   .. ..$ R     : int 2
##   .. ..$ CSharp: int 4
##   .. ..$ Python: int 3
##  $ :List of 4
##   ..$ Name     : chr "James"
##   ..$ Age      : int 25
##   ..$ Interests:List of 2
##   .. ..$ : chr "sports"
##   .. ..$ : chr "music"
##   ..$ Expertise:List of 3
##   .. ..$ R   : int 3
##   .. ..$ Java: int 2
##   .. ..$ Cpp : int 5
##  $ :List of 4
##   ..$ Name     : chr "Penny"
##   ..$ Age      : int 24
##   ..$ Interests:List of 2
##   .. ..$ : chr "movies"
##   .. ..$ : chr "reading"
##   ..$ Expertise:List of 3
##   .. ..$ R     : int 1
##   .. ..$ Cpp   : int 4
##   .. ..$ Python: int 2
  • a. list.map

    將list內特定變數打開來看

list.map(people, c(Name,Age))
## [[1]]
## [1] "Ken" "24" 
## 
## [[2]]
## [1] "James" "25"   
## 
## [[3]]
## [1] "Penny" "24"
list.map(people, sum(as.numeric(Expertise)))
## [[1]]
## [1] 9
## 
## [[2]]
## [1] 10
## 
## [[3]]
## [1] 7
  • b. list.mapv

    將map出來的list變成向量形式輸出

    抓出poeple內每個人的年紀並以向量輸出

list.mapv(people, Age)
## [1] 24 25 24
  • c. list.select

    效果類似dplyr的select

    挑選出people內的Name和Age

list.select(people, Name, Age)
## [[1]]
## [[1]]$Name
## [1] "Ken"
## 
## [[1]]$Age
## [1] 24
## 
## 
## [[2]]
## [[2]]$Name
## [1] "James"
## 
## [[2]]$Age
## [1] 25
## 
## 
## [[3]]
## [[3]]$Name
## [1] "Penny"
## 
## [[3]]$Age
## [1] 24
  • d. list.iter

    可以直接使用expression來呈現想要的結果

list.iter(people, cat(Name, ":", Age, "\n"))
## Ken : 24 
## James : 25 
## Penny : 24
  • e. list.filter

    效果類似dplyr的filter

    過濾出年紀大於等於25歲的資料

str(list.filter(people, Age >= 25))
## List of 1
##  $ :List of 4
##   ..$ Name     : chr "James"
##   ..$ Age      : int 25
##   ..$ Interests:List of 2
##   .. ..$ : chr "sports"
##   .. ..$ : chr "music"
##   ..$ Expertise:List of 3
##   .. ..$ R   : int 3
##   .. ..$ Java: int 2
##   .. ..$ Cpp : int 5
##想知道誰年紀大於等於25歲,可以用以下方式找出
list.mapv(list.filter(people, Age >= 25), Name)
## [1] "James"
##也可以利用dplyr最實用的功能之一 %>% 來運算
people %>%
  list.filter(Age >= 25) %>%
  list.mapv(Name)
## [1] "James"
  • f. list.all

    輸出結果為TRUE or FALSE,會檢視是否’每一個’變數都符合條件

    看看是否每個人的專長都有R

list.all(people, "R" %in% names(Expertise))
## [1] TRUE
  • g. list.any

    輸出結果為TRUE or FALSE,相較於list.all,只要有一個符合就會是TRUE

    看看是否有人的專長有python

list.any(people, "Python" %in% names(Expertise))
## [1] TRUE
  • h. list.sort

    根據所選變數排序,重新輸出一個list

    將三個人以年齡排序,並指選出名字和年齡

people %>%
  list.sort(Age) %>%
  list.select(Name, Age) %>%
  str
## List of 3
##  $ :List of 2
##   ..$ Name: chr "Ken"
##   ..$ Age : int 24
##  $ :List of 2
##   ..$ Name: chr "Penny"
##   ..$ Age : int 24
##  $ :List of 2
##   ..$ Name: chr "James"
##   ..$ Age : int 25

## 
## 
## 
##  ----- 
## May the force be with you . 
##  ------ 
##     \   
##      \
##                    ____
##                 _.' :  `._
##             .-.'`.  ;   .'`.-.
##    __      / : ___\ ;  /___ ; \      __
##   ,'_ ""--.:__;".-.";: :".-.":__;.--"" _`,
##   :' `.t""--.. '<@.`;_  ',@>` ..--""j.' `;
##        `:-.._J '-.-'L__ `-- ' L_..-;'
##           "-.__ ;  .-"  "-.  : __.-"
##              L ' /.------.\ ' J
##              "-.   "--"   .-"
##              __.l"-:_JL_;-";.__
##          .-j/'.;  ;""""  / .'\"-.
##          .' /:`. "-.:     .-" .';  `.
##       .-"  / ;  "-. "-..-" .-"  :    "-.
##   .+"-.  : :      "-.__.-"      ;-._   \
##   ; \  `.; ;                    : : "+. ;
##   :  ;   ; ;                    : ;  : \:
##   ;  :   ; :                    ;:   ;  :
##   : \  ;  :  ;                  : ;  /  ::
##   ;  ; :   ; :                  ;   :   ;:
##   :  :  ;  :  ;                : :  ;  : ;
##   ;\    :   ; :                ; ;     ; ;
##   : `."-;   :  ;              :  ;    /  ;
##  ;    -:   ; :              ;  : .-"   :
##   :\     \  :  ;            : \.-"      :
##   ;`.    \  ; :            ;.'_..--  / ;
##   :  "-.  "-:  ;          :/."      .'  :
##    \         \ :          ;/  __        :
##     \       .-`.\        /t-""  ":-+.   :
##      `.  .-"    `l    __/ /`. :  ; ; \  ;
##        \   .-" .-"-.-"  .' .'j \  /   ;/
##         \ / .-"   /.     .'.' ;_:'    ;
##   :-""-.`./-.'     /    `.___.'
##                \ `t  ._  /  bug
##                 "-.t-._:'
##