ข้อมูลทางชีววิทยามีหลายรูปแบบ สามาถแบ่งได้เป็น 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)
ผู้เริ่มต้นเขียนโปรแกรมสามารถใช้โปรแกรม jupyter notebook ในการเขียนคำสั่งในเซลล์ (cell) สำหรับเขียนคำสั่ง (code cell) แล้วรันคำสั่ง (run หรือ execute) เพื่อดูผลลัพธ์ (output) ที่แสดงให้เห็นได้เลย และสามารถเขียนข้อความเพื่ออธิบายประกอบคำสั่งหรือโปรแกรมในเซลล์สำหรับเขียนข้อความ (markdown cell) ได้ สามารถทดลองเขียนคำสั่งแสดงผลข้อความอย่างง่ายด้วยฟังก์ชั่น (function) print()
# first R command
print("Hello R.")
การเริ่มต้นเขียนโปรแกรมนั้นคล้ายคล้ายกับการเรียนรู้ภาษา คือเรียนรู้ตัวอักษร (character) เพื่อประกอบเป็นคำ (word) ประเภทต่างๆ แล้วสร้างเป็นประโยค (sentence) เพื่อใช้ในการสื่อสารกับหน่วยประมวลผลของคอมพิวเตอร์ให้ดำเนินการตามขั้นตอนที่ผู้เขียนโปรแกรม (programmer) ต้องการ
คำที่ใช้ในการเขียนโปรแกรมแบ่งเป็นประเภทต่างๆ ได้แก่
1. ค่าคงที่ (constant) เป็นคำที่เก็บค่าเพียงค่าเดียวและไม่สามารถเปลี่ยนแปลงได้ เช่น 1.1 จำนวน (number) ได้แก่ 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 2. ตัวแปร (variable) เป็นคำที่สามารถเปลี่ยนค่า (value) ที่เก็บไว้ภายในได้ การกำหนดชื่อตัวแปรในภาษา R ต้องไม่มีการเว้นวรรค ไม่ขึ้นต้นด้วตัวเลขหรือสัญลักษณ์ ชื่อตัวแปรที่ประกอบด้วยตัวอักษรพิมพ์ใหญ่ (uppercase) หรือเล็ก (lowercase) จะไม่เหมือนกันเช่น DNA dna หรือ Dna จะไม่ใช่ตัวแปรเดียวกัน ภายในชื่ของตัวแปรสามารถคั่นด้วย .(dot) _ (underscore) หรือมีตัวเลขได้ เช่น DNA_plant หรือ rna.sample1 3. ตัวดำเนินการ (operator) ใช้สำหรับดำเนินการคำนวนของตัวแปรหรือค่าคงที่ แบ่งเป็น 3.1 ตัวดำเนินการทางคณิตศาสตร์ (mathematical operator) ได้แก่ บวก (+) ลบ (-) คูณ (*) หาร (/) ยกกำลัง (^) ค่าสัมบูรณ์ (abs()) ลอการิทึม (log()) รากที่สอง (sqrt()) หารตัดเศษ (%/%) หารเอาส่วน (%%) 3.2 ตัวดำเนินการทางตรรกศาสตร์ สำหรับการเปรียบเทียบเชิงตรรกะ ได้แก่ และ (&) หรือ (|) นิเสธ (!) 3.3 ตัวดำเนินการเพื่อกำหนดค่าใช้เครื่องหมาย = หรือ <- 3.4 ตัวดำเนินงานสำหรับกำหนดเงื่อนไข (condition) ในการเปรียบเทียบ ได้แก่ เท่ากับ (==) ไม่เท่ากับ (!=) มากกว่า (>) น้อยกว่า (<) มากกว่าหรือเท่ากับ (>=) น้อยกว่าหรือเท่ากับ (<=) 3.5 ตัวดำเนินการพิเศษ (special operator) เช่น ; ใช้สำหรับคั่นคำสั่ง : ใช้สำหรับการกำหนดช่วงของข้อมูล (index) 4. ฟังก์ชั่น (function) เป็นชุดของคำสั่งสำหรับดำเนินการอย่างใดอย่างหนึ่งที่มีการพัฒนาไว้แล้วก่อนหน้า ผู้ใช้สามารถนำชุดคำสั่งนี้มาใช้โดยไม่จำเป็นต้องรู้ว่าฟังก์ชั่นนั้นๆ เขียนขึ้นมาอย่างไร เป็นการนำชุดคำสั่งกลับมาใช้ที่ช่วยลดระยะเวลา (reuse) ในการเขียนโปรแกรมได้ เช่น print() เป็นชุดคำสั่งสำหรับแสดงผลบนหน้าจอ mean() ชุดคำสั่งเพื่อคำนวณค่าเฉลี่ย plot() ชุดคำสั่งเพื่อแสดงผลกราฟิก (graphic) ls() เป็นชุดคำสั่งเพื่อแสดงรายการของอ็อคเจ็ค help() เป็นชุดคำสั่งเพื่อแสดงเมนูช่วยเหลือหรือเอกสารที่เกี่ยวข้องกับคำค้น getwd() เป็นชุดคำสั่งเพื่อเรียกดูตำแหน่งปัจจุบันที่ทำงานอยู่ (working directory) data() เป็นชุดคำสั่งเพื่อเรียงดูชุดข้อมูลที่มีอยู่ (data sets) หากมีฟังก์ชั่นจำนวนมากสำหรับดำเนินการในงานประเภทเดียวกัน อาจรวมกันเป็นแพคเกจ (package) และไลบรารี (library) ได้
3.14 #double
typeof(3.14) #show type
"ATG" #character
typeof("ATG")
TRUE #logical words
typeof(TRUE)
11/2 #division
11%/%2 #integer divide
11%%2 #modulus
data() #show available data sets
getwd() #get working directory
การนำคำต่างๆ ในภาษา R มาประกอบเป็นประโยคสามารถทำได้หลายรูปแบบ เช่น
#assignment
x = 10
x #display value stored in the variable
protein = "AGDFSVBBLIPPPPBNHD"
protein
#operation
y = 4
x = y + 10
x
mergedDNA = paste("AAAAA", "TTTTTT", sep="")
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 ได้ แต่ไม่ต้องกำหนดการเพิ่มหรือลดค่าของตัวแปร
#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 objects)
การเขียนโปรแกรมด้วยภาษา R เพื่อจัดการกับข้อมูลประเภทต่างๆ มีอ็อบเจ็ค (object) หรือโปรแกรมเชิงวัตถุสำหรับช่วยดำเนินการข้อมูลโดยอ็อบเจ็คจะมีลักษณะเฉพาะ (attritubue หรือ characteristics) และความสามารถของอ็อคเจ็คนั้นในการดำเนินการด้วยคำสั่งหรือฟังก์ชั่นที่เหมาะสม (method หรือ 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