ข้อมูลทางชีววิทยามีหลายรูปแบบ สามาถแบ่งได้เป็น 2 ประเภทหลัก คือ
ภาษา R พัฒนาโดย John Chambers เป็นภาษาที่นิยมใช้และมีประสิทธิภาพในการวิเคราะห์ข้อมูลทางชีววิทยารูปแบบต่างๆ สามารถติดตั้งภาษา R ได้จาก https://www.r-project.org/ ภาษา R มีการพัฒนาและปรับปรุงอย่างต่อเนื่อง มีการพัฒนาแพคเกจ (package) และไลบรารี (library) ใหม่ๆ อยู่ตลอด สามารถนำมาใช้งานโดยไม่เสียค่าใช้จ่าย การเขียนโปรแกรมด้วยภาษา R มีโปรแกรมช่วยเขียนภาษาให้เลือกใช้ได้หลายโปรแกรม เช่น RStudio หรือ [jupyter notebook] (https://jupyter.org/) ซึ่งสามาถติดตั้งได้อย่างสะดวกผ่านโปรแกรม anaconda ในการเริ่มต้นเขียนโปรแกรมภาษา R จะเปิดโปรแกรม anaconda navigator กำหนดค่า environment สำหรับภาษา R และ Python โดยเลือกเวอร์ชั่นที่เหมาะสม แล้วจึงเปิดใช้งาน jupyter notebook เพื่อเริ่มต้นการเขียนคำสั่งหรือโค้ด (coding หรือ programming หรืออาจเรียกว่า scripting)
การเขียนภาษา R ด้วยโปรแกรม RStudio สามารถดาวน์โหลดโปรแกรมนี้ได้จาก https://rstudio.com/ โดยต้องทำการติดตั้งาษา R ก่อนเช่นกัน โปรแกรม RStudio เป็นโปรแกรมช่วยเขียนภาษาที่สามารถแนะนำและตรวจแก้เบื้องต้นหากพิมพ์ผิดหลักของภาษาได้ (syntax error) โดยสามารถศึกษาวิธีใช้งานโปรแกรม RStudio เบื้องต้นได้ที่ https://youtu.be/sBCnbAdQNBM โดยไฟล์ภาษา R จะบันทึกด้วยสกุล .R ซึ่งสามารถแบ่งปันหรือเปิดกลับมาแก้ไขในภายหลังได้
ผู้เริ่มต้นเขียนโปรแกรมสามารถใช้โปรแกรม jupyter notebook ในการเขียนคำสั่งในเซลล์ (cell) สำหรับเขียนคำสั่ง (code cell) แล้วรันคำสั่ง (run หรือ execute) เพื่อดูผลลัพธ์ (output) ที่แสดงให้เห็นได้เลย และสามารถเขียนข้อความเพื่ออธิบายประกอบคำสั่งหรือโปรแกรมในเซลล์สำหรับเขียนข้อความ (markdown cell) ได้ สามารถทดลองเขียนคำสั่งแสดงผลข้อความอย่างง่ายด้วยฟังก์ชั่น (function) print()
# first R command
print("Hello R.")
การเริ่มต้นเขียนโปรแกรมนั้นคล้ายคล้ายกับการเรียนรู้ภาษา คือเรียนรู้ตัวอักษร (character) เพื่อประกอบเป็นคำ (word) ประเภทต่างๆ แล้วสร้างเป็นประโยค (sentence) เพื่อใช้ในการสื่อสารกับหน่วยประมวลผลของคอมพิวเตอร์ให้ดำเนินการตามขั้นตอนที่ผู้เขียนโปรแกรม (programmer) ต้องการ
คำที่ใช้ในการเขียนโปรแกรมแบ่งเป็นประเภทต่างๆ ได้แก่
a. จำนวนเต็ม (integer) ได้แก่ 1, 2, 3,...
b. เศษส่วนหรือทศนิยม (float หรือ double) ได้แก่ 2.3, 0.001, ...
1.2 ตัวอักษร (character) เช่น 'A' 'B' 'T' และข้อความ (string) คือลำดับของตัวอักษร เช่น 'ATGCGGACCCCA' หรือ "Cat has four legs." ค่าคงที่ประเภทนี้จะต้องเขียนอยู่ภายในเครื่องหมาย ' หรือ "
1.3 คำเฉพาะ (reserved words) สำหรับดำเนินการเฉพาะในภาษา R ได้แก่ in for while if else repeat break TRUE FALSE และ NA3.14 #double
typeof(3.14) #show type
"ATG" #character
typeof("ATG")
TRUE #logical words
typeof(TRUE)
#Basic math calculation
11/2 #division
11%/%2 #integer divide
11%%2 #modulus
11^2 #exponential
pi #Pi constant
3 == 4 #logical comparisons
100 > 50
(3 == 4) & (100 > 50)
r = 7 #assign radial value of 7 to a variable named r
circle_area = pi*r*r #calcular the area of the circle and keep the result in circle_area
circle_area #show the result
print(circle_area) #display the value kept inside the circle_area variable
# use paste function to show the result on the screen
# the showed result can be mixed between String/text and values in the variables.
paste("The area of the circle with radius of ", r, " = ", circle_area)
data() #show available data sets
getwd() #get working directory
seq(from = 2, to = 5) #function to generate a sequence of numbers
การนำคำต่างๆ ในภาษา R มาประกอบเป็นประโยคสามารถทำได้หลายรูปแบบ เช่น
#assignment
x = 10
x #display value stored in the variable
protein = "AGDFSVBBLIPPPPBNHD"
protein
nucleotide = c('A', 'T', 'C', 'G') #a variable can keep multiple values.
print(nucleotide)
#operation
y = 4
x = y + 10
x
mergedDNA = paste("AAAAA", "TTTTTT", sep="")
mergedDNA
print(mergedDNA)
paste(mergedDNA)
#comparison
x == y
(y > 10) & (y < 100)
ในตัวอย่างข้างต้น เครื่องหมาย # ใช้สำหรับเขียนข้อความที่ไม่ใช่คำสั่งภายในโปรแกรม (comments) โดยโปรแกรม R จะไม่ดำเนินการใดๆ กับข้อความเหล่านี้ สามารถใช้การเขียนคอมเมนต์เพื่ออธิบายรายละเอียดและการทำงานโปรแกรม
การนำประโยคเหล่านี้มาประกอบเป็นข้อความ (paragraph) หรือโปรแกรมที่ยาวขึ้นเพื่อดำเนินการแก้ปัญหาที่สนใจ หรือเมื่อต้องพิมพ์คำสั่งเดิมในการดำเนินการแบบเดิมซ้ำกันหลายหน ทำให้ดำเนินการได้รวดเร็วมากขึ้น สามารถใช้รูปแบบดังต่อไปนี้มาช่วยได้
#while loop
num = 1 #starting value
while(num <10){ #condition
x = paste("Gene", num, sep = "_") #command 1
print(x) #command 2
num = num + 1 #command 3
} #end of the loop
ตัวอย่างข้างต้นเป็นการใช้ while loop เพื่อกำหนดชื่อของยีนตามลำดับตัวเลข
1.2 **for loop** ใช้ในการทำซ้ำตามจำนวนหรือช่วงของจำนวนที่กำหนดในเงื่อนไขแล้วหยุดเมื่อครบตามจำนวน โดยมีรูปแบบการเขียนดังตัวอย่าง
#for loop
for(i in 1:10){ #condition
x = paste("Gene", i, sep = "_") #command 1
print(x) #command 2
}
จากตัวอย่าง สามารถใช้ for loop เพื่อทำซ้ำในการกำหนดชื่อยีนตามลำดับตัวเลขเหมือนที่เขียนด้วย while loop ได้ แต่ไม่ต้องกำหนดการเพิ่มหรือลดค่าของตัวแปร เงือนไข i in 1:10 ระบุว่าให้ R ตรวจสอบค่าของ i ว่ามีค่าอยู่ตั้งแต่ 1 ถึง 10 หรือไม่ โดย in เป็นคำเฉพาะเพื่อใช้ตรวจสอบการเป็นสมาชิกของค่าที่กำหนด และ 1:10 เป็นการกำหนดข้อมูลจำนวนนับ 1, 2, 3, ..., 10
#if...else
x = 150
if(x > 100){ #condition 1
#command if condition 1 is true
y = paste("your blood sugar is", x, "mg/dL. You have high blood sugar.")
print(y)
}else{ #condition 2
#command if condition 2 is true
y = paste("your blood sugar is", x, "mg/dL. You have normal blood sugar.")
print(y)
}
จากตัวอย่างของ if...else จะมีสองเงื่อนไข เงื่อนไขแรกของ if หากระดับน้ำตาลในเลือดมากกว่า 100 mg/dL จะพิมพ์ข้อความว่ามีระดับน้ำตาลในเลือดสูง หากไม่เป็นไปตามเงื่อนไขนี้ โปรแกรมจะดำเนินการคำสั่งในเงื่อนไขของ else หากมีหลายเงื่อนไขควรใช้ if...else if...else ดังตัวอย่างนี้
#if...else if....else
score = 70
if(score >= 80){
grade = 'A'
}else if(score >= 75 & score <80){
grade = 'B+'
}else if(score >= 70 & score <75){
grade = 'B'
}else if(score >= 65 & score <70){
grade = 'C+'
}else if(score >= 60 & score <65){
grade = 'C'
}else if(score >= 55 & score <60){
grade = 'D+'
}else if(score >= 50 & score <55){
grade = 'D'
}else{grade = 'F'}
print(paste("You got", grade, '.'))
ข้างต้นเป็นตัวอย่างการใช้ if...else if...else เพื่อระบุเกรดจากเกณฑ์คะแนนที่กำหนด ในตัวอย่างนี้มีมากกว่าสองเงื่อนไข โดยโปรแกรมจะตรวจค่าของ score กับทุกเงื่อนไข หากค่าของ score ผ่านเงื่อนไขใด โปรแกรมจะดำเนินการตามคำสั่งในเงื่อนไขนั้น คือกำหนดค่าของตัวแปร grade เพื่อแสดงผลโดยรวมข้อความด้วยฟังก์ชั่น paste() และแสดงผลที่หน้าจอด้วยฟังก์ชั่น print() หากมีเงื่อนไขย่อยภายในเงื่อนไขหลัก ควรใช้โครงสร้างแบบ nested if ดังตัวอย่าง
mom = "Aa"
dad = "Aa"
if(mom == "AA"){
if(dad == "AA"){child = "AA"
}else if(dad == "Aa"){child = "1AA : 1Aa"
}else{child = "Aa"}
}else if(mom == "Aa"){
if(dad == "AA"){child = "1AA : 1Aa"
}else if(dad == "Aa"){child = "1AA : 2Aa : 1aa"
}else{child = "1Aa : 1aa"}
}else{
if(dad == "AA"){child = "Aa"
}else if(dad == "Aa"){child = "1Aa : 1aa"
}else{child = "aa"}
}
print(paste("If mom and dad are", mom, "and", dad, ".", " The children will be", child, "."))
ตัวอย่างนี้แสดงการใช้ nested if เพื่อจับคู่จีโนไทป์ที่เป็นไปได้แต่ละแบบของแม่กับจีโนไทป์ที่เป็นไปได้ของพ่อ แล้วแสดงผลเป็นสัดส่วนจีโนไทป์ที่เป็นได้ในรุ่นลูก
ประเภทของข้อมูล (Data types หรือ data objects)
การเขียนโปรแกรมด้วยภาษา R เพื่อจัดการกับข้อมูลประเภทต่างๆ มีอ็อบเจ็ค (object) หรือโปรแกรมเชิงวัตถุสำหรับช่วยดำเนินการข้อมูลโดยอ็อบเจ็คจะมีลักษณะเฉพาะ (attritubue หรือ characteristics) และความสามารถของอ็อคเจ็คนั้นในการดำเนินการด้วยคำสั่งหรือฟังก์ชั่นที่เหมาะสม (method function หรือ ability) เช่น การสร้างอ็อบเจ็ค (creating) การตั้งชื่อ (naming) การเลือกข้อมูลที่ต้องการหรือทำดัชนี (indexing) การแทนที่ (replacing) และการดำเนินการ (operating) อ็อบเจ็คที่นิยมใช้กับข้อมูลประเภทต่างๆ ได้แก่
1. เวคเตอร์ (vector) ใช้สำหรับเก็บข้อมูลที่มีลำดับ (order) เป็นจำนวนหรือตัวอักษร โดยใช้ฟังก์ชั่น comcatenate หรือ c() เช่น
nucleotide = c('A', 'T', 'G', 'C') #create a vector named nucleotide
nucleotide
nucleotide[2] #show the second value in the vector
nucleotide[2:3] #show the second and third values
nucleotide[c(1,4)] #show the first and forth values
nucleotide[1] = 'a' #replace a value at the first position
nucleotide
2. แมทริกซ์ (matrix) เป็นอ็อบเจ็คที่เก็บข้อมูลประเภทเดียวกัน (ตัวเลข ตัวอักษร หรือตัวตรรกะ) ประกอบด้วยแถว (row) และคอลัม (column) สร้างแมทริกซ์ด้วยฟังก์ชั่น matrix() โดยระบุพารามิเตอร์ (parameter) หรืออารฺกิวเมนต์ (argument) เพื่อกำหนดจำนวนแถว (nrow) จำนวนคอลัม (ncol) จัดข้อมูลตามแนวแถว (byrow) และกำหนดชื่อคอลัมและแถว (dimnames) เช่น
nucleotide = c('A', 'T', 'G', 'C')
#create a matrix named dnaMatrix
dnaMatrix = matrix(nucleotide, nrow = 2, ncol = 2, byrow = FALSE, dimnames = list(c('purine', 'pyrimidine')))
dnaMatrix
dnaMatrix[1, 2] #select data at the first row and second column
dnaMatrix[, 2] #select only the second column
#create a vector that contains DNA nucleotide substitution values
substitutionValue = c(0.81, 0.10, 0.0, 0.02,
0.07, 0.87, 0.03, 0.03,
0.16, 0.12, 0.71, 0.01,
0.07, 0.26, 0.05, 0.62)
#create a substitution matrix
substitutionMatrix = matrix(substitutionValue, nrow = 4, ncol = 4,
byrow = TRUE, dimnames = list(c('A', 'T', 'G', 'C'), c('A', 'T', 'G', 'C')))
substitutionMatrix
substitutionMatrix[1:2, 3:4] #subset the matrix
ตัวอย่างข้างต้นอ็อบเจ็ค substitutionMatrix เป็นแมทริกซ์ขนาด 4 แถว 4 คอลัม เก็บข้อมูลความน่าจะเป็นในการเปลี่ยนแปลงนิวคลีโอไทด์ของการกลายแบบการแทนที่นิวคลีโอไทด์ จะเห็นว่าแมทริกซ์นี้เก็บข้อมูลชนิดจำนวนเท่านั้น
3. แอเรย์ (array) คือแมทริกซ์ที่มีมากกว่าสองมิติ ใช้ฟังก์ชั่น array() ในการสร้าง เช่น การสร้างแอเรย์เพื่อเก็บข้อมูลตารางรหัสพันธุกรรม เป็นตารางขนาด 8 x 8 x 2
#create a vector of codons
codon = c('UUU', 'UUC', 'UUA', 'UUG', 'UCU', 'UCC', 'UCA', 'UCG',
'UAU', 'UAC', 'UAA', 'UAG', 'UGU', 'UGC', 'UGA', 'UGG',
'CUU', 'CUC', 'CUA', 'CUG', 'CCU', 'CCC', 'CCA', 'CCG',
'CAU', 'CAC', 'CAA', 'CAG', 'CGU', 'CGC', 'CGA', 'CGG',
'AUU', 'AUC', 'AUA', 'AUG', 'ACU', 'ACC', 'ACA', 'ACG',
'AAU', 'AAC', 'AAA', 'AAG', 'AGU', 'AGC', 'AGA', 'AGG',
'GUU', 'GUC', 'GUA', 'GUG', 'GCU', 'GCC', 'GCA', 'GCG',
'GAU', 'GAC', 'GAA', 'GAG', 'GGU', 'GGC', 'GGA', 'GGG')
#Create a vector of amino acids
aminoAcid = c('Phe', 'Phe', 'Leu', 'Leu', 'Ser', 'Ser', 'Ser', 'Ser',
'Tyr', 'Tyr', 'Stop', 'Stop', 'Cys', 'Cys', 'Stop', 'Trp',
'Leu', 'Leu', 'Leu', 'Leu', 'Pro', 'Pro', 'Pro', 'Pro',
'His', 'His', 'Gln', 'Gln', 'Arg', 'Arg', 'Arg', 'Arg',
'Ile', 'Ile', 'Ile', 'Met', 'Thr', 'Thr', 'Thr', 'Thr',
'Asn', 'Asn', 'Lys', 'Lys', 'Ser', 'Ser', 'Arg', 'Arg',
'Val', 'Val', 'Val', 'Val', 'Ala', 'Ala', 'Ala', 'Ala',
'Asp', 'Asp', 'Glu', 'Glu', 'Gly', 'Gly', 'Gly', 'Gly')
#Create an array
geneticCode = array(c(codon, aminoAcid), dim = c(8, 8, 2))
print(geneticCode) #show the genetic code table
geneticCode[1,1,] #select all values from the first row and column
geneticCodeTable = data.frame(codon, aminoAcid)
#show first few rows of the table
head(geneticCodeTable)
#show last few rows of the table
tail(geneticCodeTable)
#search for an amino acid corresponding to the codon
geneticCodeTable[geneticCodeTable$codon == "UUU",]
#create a list
list_data <- list("Red", "Green", c(21,32,11), TRUE, 51.23, 119.1)
print(list_data) #show list elements
#access the list items
list_data[1]
list_data[[3]][2] #to access the inner list data, second element of the third item
list_data[1] = "black" #change the first value in the list to "black"
list_data[1]
#create a vector
data <- c("East","West","East","North","North","East","West","West","West","East","North")
print(data)
print(is.factor(data))
# Apply the factor function.
factor_data <- factor(data)
print(factor_data)
print(is.factor(factor_data))
# Apply the factor function with required order of the level.
new_order_data <- factor(factor_data,levels = c("East","West","North"))
print(new_order_data)
# Create the vectors for data frame.
height <- c(132,151,162,139,166,147,122)
weight <- c(48,49,66,53,67,52,40)
gender <- c("male","male","female","female","male","female","male")
# Create the data frame.
input_data <- data.frame(height,weight,gender)
print(input_data)
# Test if the gender column is a factor.
print(is.factor(input_data$gender))
# Print the gender column so see the levels.
print(input_data$gender)
#To create a String
a <- 'Start and end with single quote'
print(a)
b <- "Start and end with double quotes"
print(b)
c <- "single quote ' in between double quotes"
print(c)
d <- 'Double quotes " in between single quote'
print(d)
#display strings by the paste() function
a <- "Hello"
b <- 'How'
c <- "are you? "
print(paste(a,b,c))
print(paste(a,b,c, sep = "-"))
print(paste(a,b,c, sep = "", collapse = ""))
#count the number of characters
result <- nchar("Count the number of characters")
print(result)
# Total number of digits displayed. Last digit rounded off.
result <- format(23.123456789, digits = 9)
print(result)
# Display numbers in scientific notation.
result <- format(c(6, 13.14521), scientific = TRUE)
print(result)
# The minimum number of digits to the right of the decimal point.
result <- format(23.47, nsmall = 5)
print(result)
# Format treats everything as a string.
result <- format(6)
print(result)
# Numbers are padded with blank in the beginning for width.
result <- format(13.7, width = 6)
print(result)
# Left justify strings.
result <- format("Hello", width = 8, justify = "l")
print(result)
# Justfy string with center.
result <- format("Hello", width = 8, justify = "c")
print(result)
# Changing to Upper case.
result <- toupper("Changing To Upper")
print(result)
# Changing to lower case.
result <- tolower("Changing To Lower")
print(result)
#to slice the string
result <- substring("Extract", 5, 7)
print(result)
ตัวอย่างการนำข้อมูลมาศึกษาและวิเคราะห์ด้วยภาษา R
ตัวอย่างที่ 1 เป็นข้อมูลจากการศึกษาความสัมพันธ์ของขนาดร่างกาย (body size) และอัตราการเกิดเมทาบอลิซึมของสัตว์ในกลุ่ม Artiodactyla ข้อมูลนี้เก็บในรูปแบบดาต้าเฟรม ท่านคิดว่าสามารถวิเคราะห์ข้อมูลนี้ด้วยวิธีการทางสถิติอย่างไรได้บ้าง ระบุุคำถามหรือสมมติฐาน แล้ววิธีการวิเคราะห์
size_mr_data <- data.frame(
body_mass = c(32000, 37800, 347000, 4200, 196500, 100000,
4290, 32000, 65000, 69125, 9600, 133300, 150000, 407000,
115000, 67000,325000, 21500, 58588, 65320, 85000, 135000,
20500, 1613, 1618),
metabolic_rate = c(49.984, 51.981, 306.770, 10.075, 230.073,
148.949, 11.966, 46.414, 123.287, 106.663, 20.619, 180.150,
200.830, 224.779, 148.940, 112.430, 286.847, 46.347,
142.863, 106.670, 119.660, 104.150, 33.165, 4.900, 4.865),
family = c("Antilocapridae", "Antilocapridae", "Bovidae",
"Bovidae", "Bovidae", "Bovidae", "Bovidae", "Bovidae",
"Bovidae", "Bovidae", "Bovidae", "Bovidae", "Bovidae",
"Camelidae", "Camelidae", "Canidae", "Cervidae",
"Cervidae", "Cervidae", "Cervidae", "Cervidae", "Suidae",
"Tayassuidae", "Tragulidae", "Tragulidae"))
size_mr_data
ตัวอย่างที่ 2 เป็นข้อมูลจากการศึกษาปัจจัยที่มีผลต่อขนาด (size) และการสะสมคาร์บอน (carbon storage) ของไม้พุ่ม (shrub) โดยการทดลองทำใน 4 พื้นที่ (location) และศึกษาผลของปัจจัย 3 อย่าง (treatment) คือ experiment 1, 2 และ 3 ท่านคิดว่าสามารถวิเคราะห์ข้อมูลนี้ด้วยวิธีการทางสถิติอย่างไรได้บ้าง ระบุุคำถามหรือสมมติฐาน แล้ววิธีการวิเคราะห์
shrub_volume = data.frame(
site = c(rep(1, 3), rep(2, 3), rep(3, 3), rep(4, 3)),
experiment = c(rep(1:3, 4)),
length = c(2.2, 2.1, 2.7, 3, 3.1, 2.5, 1.9, 1.1, 3.5, 2.9, 4.5, 1.2),
width = c(1.3, 2.2, 1.5, 4.5, 3.1, 2.8, 1.8, 0.5, 2, 2.7, 4.8, 1.8),
height = c(9.6, 7.6, 2.2, 1.5, 4, 3, 4.5, 2.3, 7.5, 3.2, 6.5, 2.7)
)
rep(1,3)
shrub_volume