R語言學習筆記(二):常用指令

Yanwei Liu
6 min readNov 24, 2019

RStudio的快捷鍵

#產生<-
alt+-
###在 RStudio 中,我們可以按 alt 與 - 幫我們生成 <- 符號。
###<-符號相當於Pytohn的=(賦值的意思)
###也可以用=,只是有時可能會錯誤(必須依照情況判斷)
#清除Console中的內容
Ctrl+L
#離開執行中的Session
ESC(Python是Ctrl+C跳出)
#關閉RStudio
q()
#將code傳輸到console執行
將輸入標移動到欲在console執行之程式行數的末端,點擊Ctrl+Enter,即可執行
#保存Workspace(存到.RData檔案中)
save.image()
#保存dataframe(存到.RData檔案中)
save(tomato, file = "data/tomato.rdata")
#讀取保存的Workspace(.RData檔案)
load('iris.RData',.GlobalEnv)
#查詢陌生函數或物件
help(Titanic) #鐵達尼物件
help(apply) #apply函數
#查詢R目前使用的記憶體大小
memory.size()
#查詢R最大記憶體使用量
memory.limit()

基本指令

#免輸入print()直接顯示
a <- 1/pi #沒有顯示a值
(a <- 1/pi) #顯示a值
#產生註解(加上#即可,與Python相同)
#library(ggplot2)
#當前所在路徑
getwd()
#設定當前路徑到該資料夾
setwd("D:/test") #用反斜線跟重複兩次斜線同樣效果
setwd("D:\\test")
#安裝套件
install.packages("PackageName")
install.packages("coefplot_1.1.7.zip") #從zip
library(devtools)
install_github(repo="coefplot/jaredlander") #從github
#更新所有套件
update.packages()
#引入套件(library和require的差別)
library(installr) #若沒有該套件則停止運作(推薦使用)
require(installr) #若沒有該套件則false
#如果同一行需要多個指令,可以用;分開
a <- 1; b <- 1; c <- 1;
#執行已寫好的R程式
source("script.R") #不顯示訊息
source("script.R", echo = TRUE) #顯示訊息
#輸出執行結果
sink('sink.txt') #外部檔名
x<- c(1:10)
mean(x)
sink() #此時sink.txt會出現執行結果

資料的讀取與輸出

讀取txt, csv不用裝套件
讀取excel要裝套件(readxl)
讀取json要裝套件(jsonlite)

#下載
url<-"http://abc.com.tw"
download.file(url,'test.html')
在進行資料操作前先使用setwd()到工作目錄#read.csv載入CSV資料(推薦使用.csv,使用.table必須要改參數)
d <- read.csv("PathToFileName.csv",fileEncoding="UTF-8")
使用read.table讀CSV時,必須加上header=TRUE和sep=","這兩個參數#read.table載入網路csv資料(資料路徑必須用/)
url <- "https://XXXXXXXX/favorite_bands.csv"
favorite_bands <- read.table(url, header = TRUE, stringsAsFactors = FALSE, sep = ",")
#read.table載入txt資料(資料路徑必須用/)
file_path <- "test.txt"
favorite_bands <- read.table(file_path, header = TRUE, stringsAsFactors = FALSE)
View(favorite_bands)
header代表是否將資料的第一橫列設為直行的欄位名稱sep除了設定成","外,也可以改成"\t"或";"stringsAsFactors設定為FALSE(預設為TRUE)可以預防character欄位被轉換成factor-------------------------#readLines一行一行讀取(也能讀取網頁內容)(如果需要爬蟲請參考本文)
file_path <- "/Users/username/friends_script.txt"
friends_script <- readLines(file_path, n=2)#只讀2行,若全讀不用加,n=2
url = http://abc.com.tw
target = readLines(url)
target[10:19]
#read_excel讀取excel檔案(需要先將檔案下載回來,不能用網路檔案)
install.packages("readxl")
library(readxl)
file_path <- "/Users/username/favorite_bands.xlsx"
favorite_bands <- read_excel(file_path)
#fromJSON讀取json檔案
install.packages("jsonlite")
library(jsonlite)
file_path <- "/Users/username/favorite_bands.json"
favorite_bands <- fromJSON(file_path)
#write.table輸出txt檔案
favorite_bands_df <- data.frame(band = c("Beyond", "Beatles"), lead_vocal = c("Wong Ka Kui", "John Lennon"), formed = c(1983, 1960))
file_path <- "/Users/username/favorite_bands.txt"
write.table(favorite_bands_df, file = file_path, row.names = FALSE)
#write.table輸出csv檔案
favorite_bands_df <- data.frame(band = c("Beyond", "Beatles"), lead_vocal = c("Wong Ka Kui", "John Lennon"), formed = c(1983, 1960))
file_path <- "/Users/username/favorite_bands.csv"
write.table(favorite_bands_df, file = file_path, row.names = FALSE, sep = ",")
#toJSON輸出Json檔案
install.packages("jsonlite") # 如果先前已經安裝過就不用執行這行
library(jsonlite)

favorite_bands_df <- data.frame(band = c("Beyond", "Beatles"), lead_vocal = c("Wong Ka Kui", "John Lennon"), formed = c(1983, 1960))
toJSON(favorite_bands_df)
#attach&detach載入與卸載資料(就不用每次選資料都加上$符號)
attach(dataframe)
detach(dataframe)

圖檔的保存

#png可改成jpeg, tiff, bmp
png("output.png", width = 640, height = 360) # 設定輸出圖檔
hist(x) # 繪圖
dev.off() # 關閉輸出圖檔
#也可以輸出成pdf或svg
pdf("output.pdf", width = 16, height = 9)
hist(x)
dev.off()

資料型態與資料結構

#R語言預設使用double型態#NA, NaN, NULL
NA表示遺失值(Not Available),檢測方式如:is.na(x)
NaN表示無法計算的數目(例如:無限大)(Not a Number)
NULL表示空無不存在(常用來移除某個變數內容),檢測方式如:is.null(x)
#資料型態
class(5) # "numeric"
class(5.5) # "numeric"
class(5L) # "integer" #整數要在數字後面加L
class(5 + 3i) # "complex"
class(TRUE) # "logical"
class(FALSE) # "logical"
class("2017 ithome ironman") # "character"
typeof("abc") #最詳細的資料形態說明
typeof(123)
#資料型態轉換
my_logical <- TRUE
class(my_logical) # "logical"
as.numeric(my_logical) # 1
as.integer(my_logical) # 1
as.complex(my_logical) # 1+0i
as.character(my_logical) # "TRUE"
### R 語言基本的資料結構大致有五類。###vectorfactor #factor和character的不同:factor沒有" "包起來,character有" "matrixdata.framelistvector 與 factor 是處理僅有一個維度的資料結構
matrix 與 data frame 有列(row)與欄(column)的資料結構
list 就像是一個超級容器,它能夠容納不同資料結構的物件
#新增vector(Python中的List,即一般說的向量Array)
利用 c() 函數(c 意指combine)把多個數字賦值在一個物件中,這個物件的型別就稱為向量
ironman_groups <- c("Modern Web", "DevOps", "Cloud", "Big Data", "Security", "自我挑戰組")#轉換為不同的資料結構
ironman_groups_factor <- factor(ironman_groups)
ironman_groups_matrix <- matrix(ironman_groups, nrow = 2)
ironman_groups_df <- data.frame(ironman_groups)
ironman_groups_list <- list(ironman_groups, ironman_groups_factor, ironman_groups_matrix, ironman_groups_df)
### R 語言的索引值由 1 開始,這跟 Python 索引值由 0 開始有很大的區別。###ironman_groups_list[[1]]
ironman_groups_list[[2]]
#將Vector中的數值進行運算
ironmen <- c(46, 8, 11, 11, 4, 56)
articles <- ironmen * 30 articles
#製作data frame(tidyverse中的tibble與此型態類似)
groups <- c("Modern Web", "DevOps", "Cloud", "Big Data", "Security", "自我挑戰組")
ironmen <- c(46, 8, 12, 12, 6, 58)
ironmen_df <- data.frame(groups, ironmen) #合併groups和ironmen
View(ironmen_df)

迴圈與流程控制

###FOR迴圈#### 不帶索引值的寫法
ironmen <- c(49, 8, 12, 12, 6, 61)
for (ironman in ironmen) {
print(ironman)
}
# 帶索引值的寫法
for (index in 1:length(ironmen)) {
print(ironmen[index])
}
###While迴圈###ironmen <- c(49, 8, 12, 12, 6, 61)
index <- 1
while (index <= length(ironmen)) {
print(ironmen[index])
index <- index + 1
}
###流程控制####if/elseif (i %% 2 == 0) {
print(paste(i, "是偶數"))
} else {
print(paste(i, "是奇數"))
}
#if/else if/else
if (i %% 3 == 0) {
print(paste(i, "可以被 3 整除"))
} else if (i %% 3 == 1) {
print(paste(i, "除以 3 餘數是 1"))
} else {
print(paste(i, "除以 3 餘數是 2"))
}
#ifelse函式(檢測True或False並顯示指定內容)
ifelse(1 == 1, "Yes", "No") #假如1==1,顯示Yes否則No
#switchmy_seq <- 1:10
for (i in my_seq) {
ans <- i %% 3
switch(as.character(ans),
"0" = print(paste(i, "可以被 3 整除")),
"1" = print(paste(i, "除以 3 餘數是 1")),
"2" = print(paste(i, "除以 3 餘數是 2"))
)
}
#break和next
利用 break 結束迴圈。
利用 next 跳過然後繼續執行。

Pipes管線%>%

#Pipe的指令由左到右執行install.packages("magrittr")
library(magrittr)
#解釋
function(data)
data %>% function()
#使用%>%
x <- 1:10 #建立1個1~10的向量
x %>% mean #透過%>%來執行平均值計算
#使用傳統方法
X <- 1:10 #建立1個1~10的向量
mean(x) #使用mean()來執行平均值計算
#從上面的例子可能還看不出差異,下面的例子就明顯許多#傳統方法
z <- c(1, 2, NA, 8, 3, NA, 3)
sum(is.na(z))
#透過%>%一行解決,就能比較容易理解
z %>% is.na %>% sum
#一個比較完整的範例
首先,先import一個excel檔案到df變數,將它透過%>%傳到as_tibble()進行處理,再用select進行選擇,之後用mutate產生一個新變數,並且進行rename,最後print出這個資料
df <- import("data/StateData.xlsx") %>%
as_tibble() %>%
select(state_code, psychRegions,instagram:modernDance) %>%
mutate(psychRegions = as.factor(psychRegions)) %>%
rename(y = psychRegions) %>%
print()

字串(可參考另一篇stringr)

#查看字串長度
nchar('string') #6個字母
#查看向量長度
length('string')#1個單字
#連接字串
paste('I','am','a','teacher')
[1] "I am a teacher"
paste('I','am','a','teacher', sep='-')
[1] "I-am-a-teacher"
#抓取字串
substr('statistics', 1, 4) #抓取第一至第四個字母
stat
#取代字串
sub(old, new, string) #替代第一個符合
gsub(old, new, string) #替代所有符合
#印出好看的Dataframe
print.data.frame(x)

計算程式執行時間

oldtime <- proc.time()                 #初始時間
for (i in 1:50) mad(stats::runif(500)) #執行某一操作
proc.time() - oldtime #執行後減掉初始時間=執行時間

函數

#c函數
num <-1:5 #相當於 num <- c(1,2,3,4,5),C即combine的意思
#lapply函數
#將c中的1~5分別進行sum,mean,prod
lapply(c(sum,mean,prod), FUN = function(f) f(num))
#建立自訂函數
sq <- function(x) x^3 #建立sq函數,有一變數x,進行x的三次方運算
sq(2)
#範例:say.hello
say.hello <- function()
{
print("Hello, World!")
}
#範例:BMI計算
> BMI <- function(x,y) y/(x/100)^2
> BMI(180,75)

apply整批運算家族

apply                #將某運算整批套用在各列或各行
apply(x, MARGIN,FUN) #x表示變數資料, MARGIN=1或2(1橫列,2直行),FUN為函數apply(x ,2, mean) #針對X的每一直行進行平均數運算
tapply #依照元素所屬的分類作整批運算
tapply(x, INDEX,FUN) #x表示變數資料, INDEX為分組之向量或factor名稱,FUN為函數
x1
x2=as.factor(x1)
t =tapply(x1,x2,length)
lapply、sapply #對向量或List或Dataframe的每個元素作整批運算
sapply(x,FUN) #sapply盡量傳回向量或矩陣,有時傳list
sapply(df, typeof) #看df資料中所有的屬性(typeof)
lapply(x,FUN) #只傳回list
aggregate #依照兩個factor的分類組合作分群運算(向量、矩陣、Dataframe)
aggregate(x,by,FUN) #x表示變數資料,by為1個或多個變數組成的list,FUN為函數

常用函式

#資料尺度(列數與欄數)
dim(d)
nrow(d) #有幾個觀測值
ncol(d) #有幾個變數
#資料的欄位名稱(column names)
names(d)
#資料型態
typeof("abc") #最詳細
typeof(123)
#用Excel的表格來檢視資料
View(d)
#了解資料結構性質
str(d)
#快速統計資料(str和summary差別在於summary較詳細,str較粗糙)
summary(d)
#轉換資料格式
d$title <- as.Character(d$title) #轉成文字(d$title代表d裡面的title變數)
d$date <- as.Date(d$date) #轉成日期
#取得指定資料(切出子集)
subset(d, Gender =="m")
subset(d, Science >=60)
subset(d, select=c(Gender,Science,.....,....)
#查詢資料中有哪些變數(unique)
unique(d)
###函式####seq(產生一連串數字)
> seq(1, 6, by = 3)
[1] 1 4
> seq(5)
[1] 1 2 3 4 5
> seq(10,1)
[1] 10 9 8 7 6 5 4 3 2 1
#union(聯集)
> union(x=1:3, y=2:5)
[1] 1 2 3 4 5
#intersect(交集)
> intersect(x = c(1:5), y = c(2:5))
[1] 2 3 4 5
#setdiff(求向量X與向量Y中,不同的元素)
> setdiff(x=1:4, y=2:3)
[1] 1 4
#rep(產生重複數字)
> rep(10, 5)
[1] 10 10 10 10 10
#which(假如符合要求,傳回符合的數字)
which((1:12)%%2 == 0) # 1~12當中,哪些是偶數?
[1] 2 4 6 8 10 12
#使用-刪除變數中的值或內容
x <- c(1,2,3,4,5)
x[-3]
[1] 1 2 4 5 #3被去除掉了
#sample(產生隨機數字)
> sample(x=1:100, size=10)
[1]
74 26 20 19 78 39 75 48 28 94
#head,tail(顯示前幾筆或後幾筆資料)
> head(d,n=6)
> tail(d,n=6)
#order, sort, rev(排序資料)
a[order(a, decreasing=TRUE)] #大到小
sort(a, decreasing=TRUE) #大到小
x = c(55,11,44,22,33) #將向量顛倒排序(從後往前排)
rev(x)
[1] 33 22 44 11 55
#duplicated(重複值)
dup_removed=dup[!duplicated(dup)]
#縮寫變數
abbreviate(x)
#GUI編輯資料(跳出編輯室視窗)
edit(data)
#合併資料(rbind和cbind)
colnames(A)=colnames(B)=c("id","val");
rbind(A,B) #垂直合併(列資料)
cbind(A,B) #水平合併(欄資料)
#合併資料(共同欄位)(merge)#交集(未加參數預設為交集)
merge(data1, data2, by='name') #合併data1和data2,name為兩者的共同欄位
#聯集
merge(data1, data2, all = FALSE)
#grep, gsub搜尋與取代資料
grep
函數的括號,第一個東西要放你想找的關鍵字,;第二個要放的東西是你要搜尋的區域)
grep("鄉", pop$區域別) #在pop資料的"區域別"變數中找所有包含"鄉"的字
grep("鄉$", pop$區域別) #在pop資料的"區域別"變數中,只找以"鄉"為結尾的字
pop$區域別 <- gsub("區", "鄉", pop$區域別) #將"區"改成"鄉"
pop$區域別 <- gsub("區$", "鄉", pop$區域別) #將最後一字為"區"的改成"鄉"

###繪圖(內建)###
hist() #直方圖 hist(rnorm(1000))#盒形圖(應變數~類別因子, data= 資料名稱......)boxplot()
boxplot(Sepal.Length ~ Species, data = iris)
#線圖plot(..., type = "l")
plot(AirPassengers, type = "l")
#散佈圖plot()
plot(cars)
#長條圖barplot()
barplot(table(mtcars$cyl))
#曲線圖curve()
curve(sin, from = 0, to = pi * 2)
#直方圖+密度曲線
norm_dist <- rnorm(1000)
hist(norm_dist, freq = FALSE)
lines(density(norm_dist))
#加箭頭arrows()
#迴歸線abline()
#自訂標題、X軸標籤、Y軸標籤(main、xlab、ylab)
plot(cars, main = "Car speed vs. braking distance", xlab = "Car speed(mph)", ylab = "Braking distance(ft)")
#grid加入格線(繪圖後加入grid()即可)
plot(cars)
grid()
#horiz圖片改成水平方向
plot(cars,horiz = TRUE)
#las調整刻度方向
plot(cars,horiz = TRUE, las = 1)
#cex.name調整Y軸刻度字體大小
plot(cars,cex.name = 0.8)
#cex.axis調整X軸刻度字體大小
plot(cars,cex.axis= 0.8)
#繪製多個圖形
par(mfrow = c(2, 2)) #新增2x2區塊
boxplot(iris$Sepal.Length ~ iris$Species, main = "Sepal length by species")boxplot(iris$Sepal.Width ~ iris$Species, main = "Sepal width by species")boxplot(iris$Petal.Length ~ iris$Species, main = "Petal length by species")boxplot(iris$Petal.Width ~ iris$Species, main = "Petal width by species")###描述性統計###
length(d$donation) #有多少個
mean(d$donation) #平均數
sd(d$donation) #標準差
sum(d$donation) #總和
quantile(d$donation)#百分位數
range(d$donation) #全距
table(d$donation) #計數
###處理Na####
sum(d$donation,na.rm=TRUE) #移除Na
#移除缺失值
na.omit(data) #移除整行資料
#KNN填補缺失值
require(DMwR)
imputeData <- knnImputation(data)
#用平均數,填補欄位的遺漏值
mean.data <- data
mean.1 <- mean(mean.data[, 1], na.rm = T) # 第一欄位的平均數
na.rows <- is.na(mean.data[, 1]) # 第一欄位中,有遺漏值存在的資料
# 用第一欄位的平均數,填補第一欄位的遺漏值
mean.data[na.rows, 1] <- mean.1
###分組描述性統計###
tapply(d$Science, d$Gender, mean) #計算Science在不同Gender內的平均數
###線性迴歸###
lm(應變數~連續自變數,data=資料名稱)
fit <- lm(Literature~Science,data=d)
summary(fit)
anova(fit)
#繪製迴歸線
lm(Literature~Science,data=d) %>%abline()

###迴歸係數###
coef(lm物件,...)
plot(Literature~Science, data=d)
abline(a=coef(fit)[1], b=coef(fit)[2], lty=3)
###相關係數###
cor.test(資料一,資料二)
cor.test(d$Literature,d$Science)
cor.test(~ Literature+Science, data=d)
cor(d[,c(2,4:6)]) #比較所有特徵彼此間的相關係數
GGally::ggpairs(d[,c(2,4:6)) #進行相關係數繪圖

--

--