# 第一章
# 資料的輸入與輸出
#################################################
## http://biostat.tmu.edu.tw/R/20161125/#2 ##
setwd("D:/R_work/") # 設定工作目錄 # 斜線是由右到左!!
#用ls()來看
## 文字檔輸入 ##
babies = read.table("babies.txt", header=T) ## =是指派,大寫T是邏輯值!
babies = na.exclude(babies) # 刪除具有遺失值的資料
Iris = read.table("iris_dataset.txt", header=F, sep=",")
IRIS = read.csv("iris.csv", header=F)#.csv的格式也依樣是用逗號分隔
babies1 = read.fwf("babies.txt", header=T) ## =是指派,大寫T是邏輯值!
## 文字檔輸出 ##
cat(babies$smoke, file="smoke1.txt", sep="")
write(babies$smoke, file="smoke2.txt", sep=",") # ncolumns 5, 每五個換行!
weight = babies[babies$weight < 100,]
height = babies[babies$height > 70,]
write.table(weight, file="weight.txt", sep=",", row.names=F)
write.csv(height, file="height.csv", row.names=F)
## 存取其他軟體的資料檔 ##
library(gdata)
babies_xls = read.xls("babies.xls", sheet=1) # 讀取xls檔, 需要perl的路徑!
library(xlsx) #用R 32較方便,用64也其他問題!
babies_xlsx = read.xlsx("babies.xlsx", sheetIndex=2) # 讀取xlsx檔,且指定work sheet number!
write.xlsx(iris, "iris.xlsx", sheetName="iris") # 匯出xlsx檔, 可以發現速率很慢!
library(sas7bdat)
babies_sas = read.sas7bdat("babies.sas7bdat") # 讀取sas資料檔
library(foreign)
babies_spss = read.spss("babies.sav", to.data.frame=T) # 讀取spss資料檔
## 存取R物件 ##
save(weight, height, file="babies.RData")#要存幾個資料都可以 用逗號分隔!
save.image() # 儲存工作空間
load("babies.RData") #可以用 ls()來確定 已經把資料存入!
#################################################
# 第二章
# 程式流程控制
#################################################
## 邏輯判斷式 ##
## 運算子優先性:
## 括弧 => 乘除 => 加減 => 比較 => 邏輯 => 指派
x = 1
x == 3
x != 1 + 2
!(x <= 3)
x %in% 1:5 #X有在 1-5裡面嗎?!!
x < 0 || x > 5 # || 表示 or !
(is.matrix(x) || x >= 0) & (1 < 2)
## 條件執行 ##
x = 1
if (x == 3) y = 10 else y = 20
if (x >= 5) { #()小瓜號, {}大括號!
y = 15
} else {
y=0
} # 建議寫法
if (x < 0) {
y = x - 1
} else if (x > 0) { #else if, 如果不是,我在判斷x, 如果是的話...!
y = x + 1
} else {
y = x
}
## for迴圈 ## 適合我已經知道要跑幾次!!!
y = vector() # 宣告變數, 因為Y有用到 指標 []!
for (x in 1:5) { #for 迴圈就是先要說明x的範圍!!!
y[x] = sqrt(x)
}
z = 1 #起始值!
for (i in c(2,4,6,8,10)) {
z = z * i
} # 2*4*6*8*10
## while迴圈 ## 還不清楚要跑幾次!
x = 1; y = vector()
while (x <= 5) { #while 迴圈就是先有一個判斷式!
y[x] = sqrt(x)
x = x + 1
}
z = 1; i = 2
while (i <= 10) {
z = z * i
i = i + 2
}
## repeat迴圈 ##
x = 1; y = vector()
repeat {
y[x] = sqrt(x)
x = x + 1
if (x > 5) break # 跳離迴圈
}
z = 1; i = 1
repeat {
i = i + 1
if (i > 10) {break} else if (i %% 2 != 0) {next} ## "%%" i 除以 2的餘數 不等於0!!
z = z * i
} # next: 跳過一次迴圈
#################################################
# 第三章
# 自訂函數
#################################################
## R的自訂函數 ##
# 函數的定義語法:
# 自訂function名稱 = function(參數1, 參數2, ...)
# {
# 完整運算式...
# }
func1 = function(a, b)
{
x = 1+2*3/4 ##這個x只有存在此函數內, 部會影響到外面的x!!
y <<- a + b ## <<- 指派 把這個y指派到外部的變數了!!!
return(y) # 預設傳回最後一個運算值,或使用return函數
}
func1(7, 6)
func1(b=3, a=2)
## 參數的預設值 ##
func2 = function(x=0)
{
sum(x)/length(x)
}
func2(1:5)
func2() # 參數x的預設值為0
## ...參數 ##
func3 = function(x, ...) ## ... 就把此部分的參數 轉移到函數內
{
y = mean(x, ...) + 1
return(y)
}
x = c(2,4,6,NA,10)
func3(x, trim=0.1)
func3(x, trim=0, na.rm=TRUE)
## 二元運算子 ##
"%p%" = function(a, b) ## 一定要有雙引號百分比!!
{
factorial(a)/factorial(a-b)
}
5 %p% 2
#################################################
# 第四章
# 程式撰寫技巧
#################################################
## apply函數 ##
apply(iris[-5], 2, max)
func = function(x) x[x < mean(x)]
apply(iris[,1:4], 2, func)
## tapply函數 ##
tapply(iris[,1], iris[,5], min)
index2 = rep(1:2, length=150)
tapply(iris[,2], list(iris[,5],index2), median)
## sapply, lapply函數 ##
sapply(iris, length) #對每個元素, 優先回傳vector!
lapply(iris, length) #對每個元素, 回傳list!
sapply(iris[-5], function(x) { which(x > mean(x)) })
## 各方法計算時間比較 ##
x = rnorm(50000) # 以標準常態分配生成隨機樣本
y1 = y2 = y3 = y4 = vector()
t0 = proc.time() # 起始時間
for (i in 1:length(x)) {
if (x[i] <= 0) y1[i] = -1 else y1[i] = 1
}
t1 = proc.time() - t0 # y1的計算時間
y2 = ifelse(x <= 0, -1, 1)
t2 = proc.time() - t0 - t1 # y2的計算時間
y3[x <= 0] = -1; y3[x > 0] = 1
t3 = proc.time() - t0 - t1 - t2 # y3的計算時間
y4 = sapply(x, function(x) {if (x <= 0) -1 else 1})
t4 = proc.time() - t0 - t1 - t2 - t3 # y4的計算時間
## Which is better? ## #寫程式比的是 執行效率 and 開發成本(可讀性, 註解, 排版, debug)!
aa=read.table("babies.txt",header=TRUE)
bb=na.exclude(aa$smoke);cc=vector()
for(i in 1:length(bb)){if(bb[i]==1) cc[i]="是" else cc[i]="否"}
## 讀入babies資料檔、宣告smoke及new_var變數 ##
babies = read.table("babies.txt", header=TRUE)
smoke = na.exclude(babies$smoke)
new_var = vector()
## 使用迴圈將smoke變數重新編碼並存入new_var變數 ##
for (i in 1:length(smoke)) {
if (smoke[i] == 1) {
new_var[i] = "是"
} else {
new_var[i] = "否"
}
}
================================================
########################################################
## R 軟體系列課程 - R 軟體入門(二)
## 課堂練習題參考答案
## 2016/11/25
########################################################
########################
## 資料的輸入與輸出 ##
########################
## 讀入外部資料檔"babies.txt"
babies = read.table("babies.txt", header=TRUE) # 參數視資料檔內容而定
## 分別將 babies 及 iris 匯出成 csv 檔且不包含列名稱
write.csv(babies, file="babies_csv.csv", row.names=FALSE)
write.csv(iris, file="iris_csv.csv", row.names=FALSE)
## 將 babies 及 iris 儲存至同一個 RData 檔
save(babies, iris, file="datasets.RData")
####################
## 程式流程控制 ##
####################
## 利用迴圈輸出一個九九乘法表
for (i in 1:9) {
for (j in 1:9) {
cat(j, "*", i, "=", i*j, sep="")
cat("\t") # Tab對齊
}
cat("\n") # 換行
} # 可嘗試以 while 或 repeat 迴圈改寫
## 利用matrix()函數的性質, 2016/11/27 自寫!
func=function(a)
{y=matrix(,a,a)
for (i in 1:a) {
for(j in 1:a){
y[j,i]=i*j
}
}
y
}
## (亂數)產生一個1~100的整數,進行猜數字遊戲。
## 根據輸入的猜測數字提示大於或小於正確答案!
## Hint:無窮迴圈、scan()
ans = sample(10, 1) # 從1~100中隨機抽出一個值
repeat {
cat("請輸入一個介於1~100的整數:\n")
guess = scan(n=1, quiet=TRUE) # 提供使用者輸入介面
if (guess == ans) {
cat("答對囉!答案就是", ans, "!\n", sep="")
break # 重要!否則就猜不完囉~
} else {
tip = ifelse(ans > guess, "大", "小")
cat("正確答案比", guess, "還要", tip, "喔!再試一次吧!\n", sep="")
}
}
################
## 自訂函數 ##
################
## 定義一個參數為三角形三邊長的函數,回傳值為三角形種類(正三角形、等腰三角形……)
triangle = function(x)
{
sx = sort(x)
if (length(sx) != 3 || (sx[1] + sx[2]) <= sx[3]) {
return("不是三角形")
} else if (sx[1] == sx[3]) {
return("正三角形")
} else if (sx[1] == sx[2] || sx[2] == sx[3]) {
return("等腰三角形")
} else {
return("其他三角形")
}
} # 嘗試加入判斷直角三角形
## 定義一個可計算階層數的函數
## Hint:利用遞迴呼叫,0! = 1
f = function(x)
{
if (x <= 1) {
return(1)
} else {
return(x * f(x - 1))
}
}
## 定義一個可進行組合數計算的二元運算子
## 註:n 取 r 的組和數 = n! / r! / (n-r)!
"%c%" = function(n, r)
{
f(n) / f(r) / f(n - r)
}
####################
## 程式撰寫技巧 ##
####################
## 計算 babies 資料集中每一個變數的遺失值個數
func = function(x)
{
sum(is.na(x)) # 對邏輯值進行運算時,TRUE = 1;FALSE = 0
}
apply(babies, MARGIN=2, FUN=func)
## 以 smoke 為分組變數,繪製 parity 變數的次數表
tapply(babies$parity, INDEX=babies$smoke, FUN=table)
沒有留言:
張貼留言