第 6 章 Vectors
6.1 參考資料
6.2 Two types of vectors
R裡的Vectors有兩大類:
- Atomic vectors: 向量內的每個元素有相同的type, 均為numeric,均為character,均為logical等等,可使用的type有logical, integer, double, character, complex, and raw.
- 使用
c( )
將元素包起來。
- Lists: 向量內的每個元素不需要有相同type,每個元素可以是不同長度的向量。
- 使用
list( )
將元素包起來。
Atomic vector範例
a<-c(1:3)
typeof(a)
a
c(1:3)
或只寫1:3會產生
c(1,2,3)`的數值向量,因此a有3個元素,每個都是數值,其值分別是1,2,3。
每個元素我們可以用name=value
的型式對它命名:
aWithNames <- c(
a1=1,
a2=2,
a3=3
)
typeof(a)
aWithNames
List範例
b1<-list("a","b",c(1:10))
typeof(b1)
b1有三個元素:
第一個:“a”
第二個:“b”
第三個:c(1,2,3,…,10) (由
1:10
產生的1至10的數值向量)
使用name=value
命名及定義內容值:
b2<-list(
第一個="a",
第二個="b",
第三個=c(1:10))
b1
b2
6.3 Recursive objects
list元素可以是list,所以它的架構可以不停留在一個層次而可不斷加深,稱之為Recursive object,例如:
studentRecord <-
list(
學號="410073058",
姓名="王小明",
性別="男",
學年平均成績=list(
一年級=88,
二年級=90.3,
三年級=92,
四年級=95
)
)
studentRecord
6.4 Object extraction
有時我們只想取出vector裡的某個元素,以下面的list vector為例:
plasticContainer <- list(
greenBox=c("paper","scissor"), # location 1
redBox=c(1,3,2.5), # location 2
blueBox=c(TRUE,FALSE,TRUE,TRUE) # location 3
)
它有三個元素:greenBox, redBox, blueBox;各別在位置順序是1,2,3。
另外:
greenBox: 有二個沒命名的元素
redBox: 有三個沒命名的元素
blueBox: 有四個沒命名的元素
以下面的成績單物件為例:
成績單 <- c(
個經=90,
總經=77,
統計=88
)
它是什麼樣的vector? 各別元素是什麼?位置為?
6.4.1 [[.]]
extraction
[[.]]
用來取出所要的「一個」元素:
若元素有命名,
.
可用"元素名稱"
。否則,也可以用元素位置數字。
取出greenBox這個元素:
plasticContainer[["greenBox"]]
plasticContainer[[1]]
greenBox包含兩個元素:paper, scissor。如果上面要取出paper,要怎麼延伸拿取?
該元素沒命名,只能用數字。
方法一:
x <- plasticContainer[["greenBox"]]
x[[1]]
方法二:
所有extraction操作均可直接串接。
plasticContainer[["greenBox"]][[1]]
請取出前面成績單物件的個經元素。
針對studentRecord物件:
請取出姓名元素。
- 請取出三年級學年平均成績。
6.4.2 [.]
extraction
[.]
用來取出所要的「一群」元素:
若元素有命名,
.
可用c("元素名稱1","元素名稱2",...)
。否則,也可以用元素位置數字, 如
c(2,4)
代表第2及第4個元素。
同時取出greenBox及redBox兩個元素:
plasticContainer[c("greenBox","redBox")]
plasticContainer[c(1,2)]
要留意[.]
所取出的物群會以母層vector結構保存。以plasticContainer[c(1,2)]
為例,取出的物群來自一個為list vector結構的母層,所以它也會是個list vector,也就是說它相當於以下的list vector:
list(
greenBox=c("paper","scissor"),
redBox=c(1,3,2.5)
)
對照一下源頭母層的定義會更清楚:
plasticContainer <- list(
greenBox=c("paper","scissor"),
redBox=c(1,3,2.5),
blueBox=c(TRUE,FALSE,TRUE,TRUE)
)
[.]
是用來取出一群元素,當然一群的個數也可以是一個,然而以[.]
和[[.]]
取一個元素的結果會有一些不同。以下兩者取出來的結果其class為什麼?
extract1 <- plasticContainer[c("greenBox")]
extract2 <- plasticContainer[[c("greenBox")]]
請各自由extract1及extract2取出“paper”元素值。
另一個[.]
extraction可以接受的是使用logical vector來對應「個別」元素要(TRUE)/不要(FALSE)取出來;由於是對應「個別」元素,所以logical vector長度要和物件內元素個數一樣。
length(plasticContainer)
plasticContainer[c(T,F,T)]
成績單
成績單[c(FALSE,TRUE,TRUE)]
若確定只要取「一個」元素,建議用[[.]]
;後續程式寫作比較不會出現錯誤。
6.4.3 $.
extraction
$.
:
只能用在list vector,且
只能取「一個」元素,其中
.
一定為「元素名稱」。
以下兩者相同:
plasticContainer$greenBox
plasticContainer[["greenBox"]]
6.4.4 範例:Github commit記錄
這個範例必需先安裝httr, stringr套件
your_github_username <- "tpemartin"
your_practice_reponame <- "107-2-inclass-practice"
library(httr)
library(stringr)
str_replace_all(
"https://api.github.com/repos/:owner/:repo/commits",
c(
":owner"=your_github_username,
":repo"=your_practice_reponame
)
) -> commitCheckStatement
commitCheck <- content(GET(commitCheckStatement))
commitCheck是個list vector,裡面每個元素(沒命名)各自代表一次commit紀錄。請取出第4個commit紀錄的commit時間(為UTC time),並轉成台灣時間。
有一種date time格式如“2019-04-10T14:38:45Z”,它是ISO8601標準下的一種寫法,其中Z表示此格式為UTC時間——許多國際性的公司如Google, GitHub等都是用ISO8601格式在記錄日期時間。
6.4.5 範例:Plotly
請先安裝plotly
install.packages("plotly")
下載繪圖成品(源自:https://plot.ly/~neda/4070)
download.file("https://github.com/tpemartin/github-data/blob/master/plotly_4070_neda.Rda?raw=true",destfile = "plotly_4070_neda.Rda")
load("plotly_4070_neda.Rda")
library(plotly)
plotly_4070_neda
plotly_4070_neda$x$layout$shapes[[1]]$opacity<-0.8
plotly_4070_neda
6.4.6 範例:str_split
第三屆經濟播客競賽人氣投票結果在以下的favoriteTwo物件裡
library(readr)
filmVotingData <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/podcastcompetition3.csv")
str_replace(filmVotingData$請選擇你最喜歡的影片二部,", by"," by") -> favoriteTwo
birthday <- filmVotingData$`出生西元年月日(驗證本人用)`
timeStamp <- filmVotingData$Timestamp
favoriteTwo的每個元素是一位同學選出的兩部片片名,中間用逗號空一格分隔,即
,
。birthday是出生日期。
timeStamp是交作業時間
library(stringr)
str_split(favoriteTwo,", ") -> favoriteTwoList # 將選擇的兩片split成兩個元素
unlist(favoriteTwoList) -> allVotes # 將list堆疊成atomic vector
table(allVotes) # 計算每個類別的次數
birthday只能有8位元,
str_length()
可計算每個元素的位元長度。請產生一個logical vector稱為logiCorrect,TRUE表示剛好8位元。只留下birthday輸入正確的人,請統計各別片名支持人數。
若只留下凌晨1點(含)到早上5點(含)的投票人,他們的出生年份統計為何。