ข้อมูลความหลากหลายทางชีวภาพเป็นข้อมูลที่พวกเราได้มาอย่างยากลำบาก กว่าจะเก็บตัวอย่าง กว่าจะระบุชนิดสิ่งมีชีวิตแต่ละตัวได้นั้น ล้วนใช้ทรัพยากรเงิน บุคลากร และ เวลาไปเป็นอย่างมาก ฉะนั้นแล้ว เราจะพยายามนำข้อมูลที่ได้มาได้นี้มาใช้ให้เกิดประโยชน์มากที่สุดเท่าที่จะทำได้ ผ่านการวิเคราะห์ข้อมูลในรูปแบบต่าง ๆ ที่จะสามารถนำไปใช้อธิบายรูปแบบความหลากหลายที่เราสำรวจได้อย่างเป็นระบบมากขึ้น
ใน workshop ครั้งนี้ เราจะให้ทุกท่านได้เริ่มเรียนรู้การใช้ R (สำหรับคนที่ไม่เคยใช้) ไปพร้อม ๆ กับการวิเคราะห์ความหลากหลายทางชีวภาพ ซึ่งเราจะใช้ข้อมูลพื้นฐานคือ
หน่วยการเก็บตัวอย่าง (Sampling Unit) เช่น แปลง สถานที่ ถาด บ่อ อำเภอ จังหวัด เป็นต้น
หน่วยอนุกรมวิธานที่สนใจ (Operational Taxonomic Units: OTUs) เช่น ชนิด สกุล วงศ์ เป็นต้น
จำนวนของสิ่งมีชีวิตนั้น ๆ ในแต่ละหน่วยการเก็บตัวอย่างและหน่วยอนุกรมวิธาน (Abundance) เช่น จำนวนตัว จำนวน read ร้อยละการปกคลุม เป็นต้น หากไม่ได้เก็บค่าจำนวนมา อาจใช้การพบหรือไม่พบ (absence/presence) แทนได้เช่นกัน
ถ้าเรามีข้อมูลเหล่านี้แล้ว ก็สามารถนำมาใช้วิเคราะห์ข้อมูลได้ในหลากหลายรูปแบบ ตามวัตถุประสงค์และคำถามวิจัยของแต่ละท่าน workshop นี้จะให้เครื่องมือแก่ท่านในการนำไปใช้วิเคราะห์ข้อมูลด้วยตนเองในอนาคต หรือ อย่างน้อยที่สุด ได้ทราบถึงแนวทางการวิเคราะห์ข้อมูลที่ได้จากการทำงานวิจัยด้านอนุกรมวิธาน
Platform ที่เราใช้อยู่นี้คือ RStudio ที่อยู่ออนไลน์ อยู่บน server ของบริษัท Posit ซึ่งทำให้เราสามารถใช้ R ที่ไหนก็ได้ผ่าน browser บนคอมพิวเตอร์ หรือ แม้กระทั่ง tablet แต่จะต้องมีอินเตอร์เน็ตอยู่ตลอดเวลา ถ้าท่านใดต้องการที่จะทำการวิเคราะห์จำนวนมาก อาจจะพิจารณาติดตั้งโปรแกรม RStudio ในเครื่องของท่านเองได้
เราจะเริ่มด้วยการนำเข้า packages เสริม ซึ่งก็คือ ชุดคำสั่งเพิ่มเติมจาก R พื้นฐาน (base R) ที่จะทำให้การทำงานของเราง่ายขึ้น โดยตัว โค้ดทั้งหมด จะอยู่ในแถบสีเทาด้านล่าง และ เราสามารถให้โค้ดทำงาน (Run Code) ได้โดยการกดปุ่ม Play สีเขียวที่มุมขวาบนของแต่ละกล่อง
หากมีตัวอักษรสีแดงจำนวนมากขึ้นมา ไม่ต้องตกใจนะครับ เป็นการแสดงว่า package เหล่านี้ได้รับการโหลดขึ้นมาเรียบร้อยแล้ว
library(vegan)
## Loading required package: permute
## Loading required package: lattice
## This is vegan 2.6-4
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.2 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.4.2 ✔ tibble 3.2.1
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(picante)
## Loading required package: ape
##
## Attaching package: 'ape'
##
## The following object is masked from 'package:dplyr':
##
## where
##
## Loading required package: nlme
##
## Attaching package: 'nlme'
##
## The following object is masked from 'package:dplyr':
##
## collapse
library(broom)
library(pheatmap)
library(RColorBrewer)
library(ggfortify)
เราสามารถนำข้อมูลในรูปแบบไฟล์ csv (comma separated value) ซึ่งสามารถ Save
As ได้จาก Microsoft Excel หรือ โปรแกรมอื่น ๆ โดยใช้คำสั่ง read.csv
และนำผลที่อ่านได้ไปเก็บใน object ใหม่ ที่เราจะตั้งชื่อว่า
sample.sheet
จะเห็นว่าข้อมูลแบบนี้เป็นการจดแบบง่ายโดยให้คอลัมน์แรกเป็นหน่วยการเก็บข้อมูล
(plot ในที่นี้) และ คอลัมน์ถัดมาเป็น จำนวนตัว
(abundance) และตามมาด้วยชื่อชนิดในคอลัมน์ชื่อ sp
sample_sheet <- read.csv("sample_sheet.csv")
sample_sheet
## plot abundance sp
## 1 site1 2 sp_a
## 2 site1 5 sp_b
## 3 site2 3 sp_b
## 4 site2 1 sp_c
## 5 site2 2 sp_d
## 6 site2 1 sp_e
## 7 site3 4 sp_e
## 8 site3 10 sp_f
ข้อมูลในลักษณะข้างต้น จะต้องมีการเปลี่ยนรูปแบบไปอยู่ในรูปแบบของ เมทริกซ์ (matrix)
เพื่อการคำนวณต่าง ๆ ต่อไป โดยสามารถใช้คำสั่งสำเร็จรูป sample2matrix
ได้ดังนี้
sample_mat <- sample2matrix(sample_sheet)
sample_mat
## sp_a sp_b sp_c sp_d sp_e sp_f
## site1 2 5 0 0 0 0
## site2 0 3 1 2 1 0
## site3 0 0 0 0 4 10
วิธีการนี้จะช่วยลดความผิดพลาดในการบันทึกข้อมูลในรูปแบบ matrix ตั้งแต่แรกที่ต้องมาเติม 0 ในช่องที่ไม่พบสิ่งมีชีวิตแบบเอง ยิ่งถ้าข้อมูลยิ่งเยอะ จะมีโอกาสผิดพลาดได้เยอะขึ้น
แต่ถ้าเรามีข้อมูลในรูปแบบ matrix อยู่แล้ว ก็สามารถนำเข้าในโปรแกรมได้เลยดังนี้ ข้อมูลด้านล่างนี้เป็นตัวอย่างข้อมูลสังคมพืชจากพื้นที่สันทราย (sand dune) แห่งหนึ่ง ที่มีการวางแปลงย่อย 20 แปลง และพบพืชทั้งหมด 30 ชนิด แหล่งที่มาข้อมูลสังคมพืชบนสันทราย
dune_comm <- read.csv("dune_comm.csv", row.names = 1)
dune_comm
## Achimill Agrostol Airaprae Alopgeni Anthodor Bellpere Bromhord Chenalbu
## 1 1 0 0 0 0 0 0 0
## 2 3 0 0 2 0 3 4 0
## 3 0 4 0 7 0 2 0 0
## 4 0 8 0 2 0 2 3 0
## 5 2 0 0 0 4 2 2 0
## 6 2 0 0 0 3 0 0 0
## 7 2 0 0 0 2 0 2 0
## 8 0 4 0 5 0 0 0 0
## 9 0 3 0 3 0 0 0 0
## 10 4 0 0 0 4 2 4 0
## 11 0 0 0 0 0 0 0 0
## 12 0 4 0 8 0 0 0 0
## 13 0 5 0 5 0 0 0 1
## 14 0 4 0 0 0 0 0 0
## 15 0 4 0 0 0 0 0 0
## 16 0 7 0 4 0 0 0 0
## 17 2 0 2 0 4 0 0 0
## 18 0 0 0 0 0 2 0 0
## 19 0 0 3 0 4 0 0 0
## 20 0 5 0 0 0 0 0 0
## Cirsarve Comapalu Eleopalu Elymrepe Empenigr Hyporadi Juncarti Juncbufo
## 1 0 0 0 4 0 0 0 0
## 2 0 0 0 4 0 0 0 0
## 3 0 0 0 4 0 0 0 0
## 4 2 0 0 4 0 0 0 0
## 5 0 0 0 4 0 0 0 0
## 6 0 0 0 0 0 0 0 0
## 7 0 0 0 0 0 0 0 2
## 8 0 0 4 0 0 0 4 0
## 9 0 0 0 6 0 0 4 4
## 10 0 0 0 0 0 0 0 0
## 11 0 0 0 0 0 2 0 0
## 12 0 0 0 0 0 0 0 4
## 13 0 0 0 0 0 0 0 3
## 14 0 2 4 0 0 0 0 0
## 15 0 2 5 0 0 0 3 0
## 16 0 0 8 0 0 0 3 0
## 17 0 0 0 0 0 2 0 0
## 18 0 0 0 0 0 0 0 0
## 19 0 0 0 0 2 5 0 0
## 20 0 0 4 0 0 0 4 0
## Lolipere Planlanc Poaprat Poatriv Ranuflam Rumeacet Sagiproc Salirepe
## 1 7 0 4 2 0 0 0 0
## 2 5 0 4 7 0 0 0 0
## 3 6 0 5 6 0 0 0 0
## 4 5 0 4 5 0 0 5 0
## 5 2 5 2 6 0 5 0 0
## 6 6 5 3 4 0 6 0 0
## 7 6 5 4 5 0 3 0 0
## 8 4 0 4 4 2 0 2 0
## 9 2 0 4 5 0 2 2 0
## 10 6 3 4 4 0 0 0 0
## 11 7 3 4 0 0 0 2 0
## 12 0 0 0 4 0 2 4 0
## 13 0 0 2 9 2 0 2 0
## 14 0 0 0 0 2 0 0 0
## 15 0 0 0 0 2 0 0 0
## 16 0 0 0 2 2 0 0 0
## 17 0 2 1 0 0 0 0 0
## 18 2 3 3 0 0 0 0 3
## 19 0 0 0 0 0 0 3 3
## 20 0 0 0 0 4 0 0 5
## Scorautu Trifprat Trifrepe Vicilath Bracruta Callcusp
## 1 0 0 0 0 0 0
## 2 5 0 5 0 0 0
## 3 2 0 2 0 2 0
## 4 2 0 1 0 2 0
## 5 3 2 2 0 2 0
## 6 3 5 5 0 6 0
## 7 3 2 2 0 2 0
## 8 3 0 2 0 2 0
## 9 2 0 3 0 2 0
## 10 3 0 6 1 2 0
## 11 5 0 3 2 4 0
## 12 2 0 3 0 4 0
## 13 2 0 2 0 0 0
## 14 2 0 6 0 0 4
## 15 2 0 1 0 4 0
## 16 0 0 0 0 4 3
## 17 2 0 0 0 0 0
## 18 5 0 2 1 6 0
## 19 6 0 2 0 3 0
## 20 2 0 0 0 4 3
ก่อนที่จะเริ่มวิเคราะห์ใด ๆ เราจะเริ่มแสดงภาพความหลากหลายของเราเสียก่อนเพื่อให้เราเข้าใจข้อมูลของเรามากขึ้น โดยจะใช้การแสดงผลที่เรียกว่า heatmap ซึ่งจะมาในรูปแบบของตารางที่ในแต่ละช่องจะแสดงจำนวน (abundance) ของสิ่งมีชีวิตผ่านสีต่าง ๆ โดยสามารถวาดได้หลายรูปแบบดังนี้
ในแบบนี้จะเรียงลำดับตามข้อมูลที่เราระบุใน matrix ของเรา
pheatmap(sample_mat, cluster_rows = FALSE, cluster_cols = FALSE)
ในแบบที่เป็น default ของ function จะมีการเรียงลำดับ plot และ species ตามความเหมือน (similarity) เพื่อจะทำให้เราเห็น pattern ภายในข้อมูลมากขึ้น
pheatmap(sample_mat)
เราสามารถปรับสีได้ดังนี้
my_color <- colorRampPalette(c("white", "brown", "red"))(50)
pheatmap(sample_mat, color = my_color)
หรือจะใช้ palette ที่มีอยู่แล้วโดยเลือกได้จาก palette ด้านล่างนี้ได้เลย
my_color <- colorRampPalette(brewer.pal(n = 9, name = "Greens"))(50)
pheatmap(sample_mat, color = my_color)
ในแบบฝึกหัดนี้ เราจะลองนำเข้าข้อมูลใหม่ ซึ่งเป็นข้อมูลของนกในไต้หวันที่มีการเก็บข้อมูลจำนวน 50 แปลงตามระดับความสูงจากระดับน้ำทะเลที่แตกต่างกัน (https://www.davidzeleny.net/anadat-r/doku.php/en:data:ybirds) ให้แต่ละท่านลองดำเนินการต่อไปนี้
1.1 อ่านไฟล์ bird_comm.csv เข้าโปรแกรม จะพบนกทั้งหมด 59 ชนิด
จาก 50 แปลง.
1.2 วาด heatmap เพื่อแสดงภาพความหลากหลายในข้อมูลนี้
ในการพิจารณาความหลากหลายทางชีวภาพเราสามารถพิจารณาความหลากหลายได้ 3 ระดับดังต่อไปนี้
\(\alpha\) diversity (alpha diversity) = ความหลากหลายในแต่ละหน่วยเก็บข้อมูล บางครั้งเรียกว่า local diversity ซึ่งขอบเขตของหน่วยเก็บข้อมูลส่วนมากจะเป็นแปลงศึกษา หรือ พรมแดนธรรมชาติที่ผู้วิจัยกำหนด
\(\beta\) diversity (beta diversity) = ความแตกต่างขององค์ประกอบชนิดระหว่างหน่วยเก็บข้อมูล ซึ่งมีสูตรคำนวณความแตกต่างนี้จำนวนมาก ขึ้นกับวัตถุประสงค์ของผู้วิจัย
\(\gamma\) diversity (gamma diversity) = ความหลากหลายของทุกหน่วยเก็บข้อมูลร่วมกัน บางครั้งอาจจะเรียกว่า regional diversity หรือ ความหลากหลายระดับภูมิภาค ซึ่งจะขึ้นอยู่กับผู้วิจัยว่าจะกำหนดให้ “ภูมิภาค” ครอบคลุมแค่ไหน แต่ส่วนมากจะหมายถึงความหลากหลายโดยรวมของการศึกษาในครั้งนั้น ๆ
ใน workshop วันนี้ เราจะพาทุกท่านไปสำรวจความหลากหลายที่ระดับต่าง ๆ จากข้อมูล
dune_comm กันนะครับ
เราสามารถนับจำนวนชนิดของทุกแปลงรวมกัน โดยพิจารณาชนิดที่ซ้ำกันโดยเริ่มจาก บวกรวมค่า
abundance ของแต่ละชนิด (ที่อยู่ในแต่ละคอลัมน์กันก่อน ด้วยคำสั่ง
colSums
colSums(dune_comm)
## Achimill Agrostol Airaprae Alopgeni Anthodor Bellpere Bromhord Chenalbu
## 16 48 5 36 21 13 15 1
## Cirsarve Comapalu Eleopalu Elymrepe Empenigr Hyporadi Juncarti Juncbufo
## 2 4 25 26 2 9 18 13
## Lolipere Planlanc Poaprat Poatriv Ranuflam Rumeacet Sagiproc Salirepe
## 58 26 48 63 14 18 20 11
## Scorautu Trifprat Trifrepe Vicilath Bracruta Callcusp
## 54 9 47 4 49 10
จากข้อมูลนี้ เราก็จะนับชนิดที่มีมากกว่า 0 เป็นจำนวนชนิดที่พบ ด้วยคำสั่ง
length ก็จะพบว่า \(\gamma\)
diversity ของทั้งชุดข้อมูลนี้คือ 30 ชนิดนั่นเอง
length(colSums(dune_comm) > 0)
## [1] 30
Species Accumulation Curve
จะแสดงให้เราเห็นว่าการเก็บตัวอย่างของเราทั้งหมดนั้น
ใกล้เคียงจำนวนตัวอย่างที่ควรจะพบในพื้นที่ทั้งหมดนั้นหรือยัง
โดยโปรแกรมจะทำการวาดกราฟแสดงจำนวนชนิด สะสม
ที่เพิ่มขึ้นเมื่อเพิ่มจำนวนหน่วยเก็บข้อมูล (sampling unit)
และจะทำการสุ่มให้ด้วยว่าที่จำนวนแปลงเท่ากันนี้ หากเลือกคำนวณชนิดสะสมจากคนละแปลงกัน
จะได้จำนวนชนิดสะสมเท่าไหร่ ทั้งหมดนี้ดำเนินการด้วยคำสั่ง specaccum
(vegan package)
dune_specaccum <- specaccum(dune_comm)
dune_specaccum
## Species Accumulation Curve
## Accumulation method: exact
## Call: specaccum(comm = dune_comm)
##
##
## Sites 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.00000
## Richness 9.850000 15.110526 18.510526 20.937461 22.754321 24.149587 25.23956
## sd 2.351064 1.876385 1.572271 1.446958 1.390159 1.353035 1.31648
##
## Sites 8.000000 9.000000 10.000000 11.000000 12.000000 13.000000 14.00000
## Richness 26.103548 26.798244 27.364962 27.833984 28.227546 28.562036 28.84964
## sd 1.274903 1.228201 1.176341 1.119344 1.056454 0.987409 0.91160
##
## Sites 15.000000 16.000000 17.00000 18.000000 19.000000 20
## Richness 29.099587 29.319092 29.51403 29.689474 29.850000 30
## sd 0.828689 0.738092 0.63339 0.513971 0.357071 0
ซึ่งคำสั่ง specaccum
นี้จะให้ค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐานของจำนวนชนิดสะสมในแต่ละแปลง ซึ่งหากเราให้คำสั่ง
plot ก็จะสามารถวิเคราะห์ข้อมูลนี้ได้ดีขึ้น
plot(dune_specaccum)
เส้นโค้งคือ accumulation curve ที่แสดงแนวโน้มจำนวนชนิดสะสม และ เส้นแนวตั้งคือจำนวนชนิดสะสมเฉลี่ย ± ส่วนเบี่ยงเบนมาตรฐาน (standard deviation)
เราสามารถปรับกราฟให้สวยงามขึ้นได้ดังนี้
plot(dune_specaccum, ci.type = "polygon", ci.col = "#57F3C7", ci.lty = 0)
ในกรณีที่เราคิดว่าจำนวนชนิดที่พบยังไม่ใกล้เคียงที่จำนวนที่ควรจะพบทั้งหมดได้ เราสามารถคำนวณจำนวนที่ชนิดที่ควรจะพบ หรือ จำนวนชนิดทั้งหมด (species pool) ด้วย สูตรประมาณค่าความหลากหลาย (diversity estimators) ต่าง ๆ ดังนี้
specpool(dune_comm)
## Species chao chao.se jack1 jack1.se jack2 boot boot.se n
## All 30 32.1375 3.242503 32.85 1.645448 33.84474 31.5404 1.153121 20
รายละเอียดของการคำนวณแต่ละค่านั้นสามารถดูได้ที่
help("specpool")
ในแบบฝึกหัดถัดไปเราจะใช้ข้อมูลนกจาก challenge แรก มาดู gamma diversity
2.1 วาด species accumulation curve เพื่อดูว่าการเก็บตัวอย่างไรสมบูรณ์หรือยัง
2.2 คำนวณจำนวนชนิดของนกทั้งหมดที่ควรพบในการศึกษาครั้งนี้
วิธีการอธิบายความหลากหลายที่ง่ายที่สุดก็คือจำนวนชนิด หรือ species richness ซึ่งเราสามารถจำนวนของแต่ละแปลงได้ดังต่อไปนี้
dune_richness <- specnumber(dune_comm)
dune_richness
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
## 5 10 10 13 14 11 13 12 13 12 9 9 10 7 8 8 7 9 9 8
ในหลายกรณี เราจะมีข้อมูลเพิ่มเติมของแต่ละแปลงด้วยว่ามีลักษณะอย่างไร เราจะเรียกข้อมูลเหล่านี้ว่า “environmental data” ซึ่งเราอ่านเข้ามาได้ดังนี้
dune_env <- read.csv("dune_env.csv", row.names = 1)
dune_env
## A1 Moisture Management Use Manure
## 1 2.8 1 SF Haypastu 4
## 2 3.5 1 BF Haypastu 2
## 3 4.3 2 SF Haypastu 4
## 4 4.2 2 SF Haypastu 4
## 5 6.3 1 HF Hayfield 2
## 6 4.3 1 HF Haypastu 2
## 7 2.8 1 HF Pasture 3
## 8 4.2 5 HF Pasture 3
## 9 3.7 4 HF Hayfield 1
## 10 3.3 2 BF Hayfield 1
## 11 3.5 1 BF Pasture 1
## 12 5.8 4 SF Haypastu 2
## 13 6.0 5 SF Haypastu 3
## 14 9.3 5 NM Pasture 0
## 15 11.5 5 NM Haypastu 0
## 16 5.7 5 SF Pasture 3
## 17 4.0 2 NM Hayfield 0
## 18 4.6 1 NM Hayfield 0
## 19 3.7 5 NM Hayfield 0
## 20 3.5 5 NM Hayfield 0
ในข้อมูลนี้จะแสดงข้อมูลของแต่ละแปลง ดังต่อไปนี้
A1 = ความหนาของดินชั้น A1
Moisture = ระดับความชื้นจากน้อยไปมาก (1 -> 5)
Management = การจัดการพื้นที่
BF Biological farming
HF Hobby farming
NM Nature Conservation Management และ
SF Standard Farming
Use = ระดับการใช้พื้นที่ : Hayfield (ที่ปลูกฟาง รบกวนน้อยสุด)
< Haypastu < Pasture (ทุ่งหญ้าเลี้ยงสัตว์
รบกวนมากสุด)
Manure = ระดับการใส่ปุ๋ยคอกจากน้อยไปมาก (0->4)
เราสามารถคำนวณจำนวนชนิดให้แยกตามปัจจัยต่าง ๆ ที่เราเพิ่งนำเข้าได้ ดังนี้
specnumber(dune_comm, groups = dune_env$Management)
## BF HF NM SF
## 16 21 21 21
ในหลายครั้ง จำนวนชนิดก็ไม่ได้บอกทุกอย่างเกี่ยวกับพื้นที่ที่เราศึกษา เราลองพิจารณาภาพของ 2 พื้นที่ที่มีจำนวนชนิดเท่ากัน (richness = 4) ด้านล่าง
จะเห็นว่าด้านล่างจะดูหลากหลายกว่า ทั้ง ๆ ที่จำนวนชนิดเท่ากัน อันนี้เป็นเพราะว่า แต่ละชนิดในภาพล่าง มีจำนวนพอ ๆ กัน (even abundance) เลยทำให้ดูหลายกหลายกว่า เราสามารถนับจำนวนของแต่ละชนิดมาร่วมคำนวณเพื่อหาความหลากหลายด้วย เราจะเรียกค่านี้ว่า ดัชนีความหลากหลาย (diversity index) ซึ่งจะขอยกตัวอย่างการคำนวณ Shannon’s diversity index ซึ่งมีสูตรคำนวณดังนี้
\[H = -\sum_{i=1}^{n}(p_{i}~ln~p_{i})\] โดย \(p_{i}\) คือสัดส่วนจำนวนตัวของชนิดนั้น ๆ ในสังคมสิ่งมีชีวิตทั้งหมด เราสามารถให้โปรแกรมช่วยคำนวณได้ดังนี้
dune_shannon <- diversity(dune_comm)
dune_shannon
## 1 2 3 4 5 6 7 8
## 1.440482 2.252516 2.193749 2.426779 2.544421 2.345946 2.471733 2.434898
## 9 10 11 12 13 14 15 16
## 2.493568 2.398613 2.106065 2.114495 2.099638 1.863680 1.979309 1.959795
## 17 18 19 20
## 1.876274 2.079387 2.134024 2.048270
ดัชนี้นี้ไม่มีหน่วยและตัวเลขที่ได้อาจจะไม่สามารถเทียบเคียงได้กับการศึกษาอื่น ๆ โดยตรง เพราะค่าที่ได้จะขึ้นอยู่กับจำนวนชนิดทั้งหมดด้วย ดังนั้น ค่านี้จึงเหมาะกับการเปรียบเทียบภายในการศึกษาเดียวกัน
และก็สามารถคำนวณแยกกลุ่มตามปัจจัยที่สนใจได้เช่นเคย
diversity(dune_comm, groups = dune_env$Management)
## BF HF NM SF
## 2.566756 2.870434 2.807265 2.684520
หนึ่งในประโยชน์ของการวิเคราะห์ข้อมูลเหล่านี้ใน R คือ เราสามารถเชื่อมโยงข้อมูลที่คำนวณได้ใหม่กับข้อมูลอื่น ๆ โดยที่ไม่ต้อง copy-paste ใน Excel เลย ช่วยลดความผิดพลาดในการคำนวณได้ดีขึ้น
ตัวอย่างด้านล่างนี้เราจะเพิ่มคอลัมน์ในไฟล์ dune_env เดิม
เพื่อรองรับข้อมูล species richness และ Shannon’s index ดังนี้
dune_env$richness <- dune_richness
dune_env$shannon <- dune_shannon
dune_env
## A1 Moisture Management Use Manure richness shannon
## 1 2.8 1 SF Haypastu 4 5 1.440482
## 2 3.5 1 BF Haypastu 2 10 2.252516
## 3 4.3 2 SF Haypastu 4 10 2.193749
## 4 4.2 2 SF Haypastu 4 13 2.426779
## 5 6.3 1 HF Hayfield 2 14 2.544421
## 6 4.3 1 HF Haypastu 2 11 2.345946
## 7 2.8 1 HF Pasture 3 13 2.471733
## 8 4.2 5 HF Pasture 3 12 2.434898
## 9 3.7 4 HF Hayfield 1 13 2.493568
## 10 3.3 2 BF Hayfield 1 12 2.398613
## 11 3.5 1 BF Pasture 1 9 2.106065
## 12 5.8 4 SF Haypastu 2 9 2.114495
## 13 6.0 5 SF Haypastu 3 10 2.099638
## 14 9.3 5 NM Pasture 0 7 1.863680
## 15 11.5 5 NM Haypastu 0 8 1.979309
## 16 5.7 5 SF Pasture 3 8 1.959795
## 17 4.0 2 NM Hayfield 0 7 1.876274
## 18 4.6 1 NM Hayfield 0 9 2.079387
## 19 3.7 5 NM Hayfield 0 9 2.134024
## 20 3.5 5 NM Hayfield 0 8 2.048270
ข้อมูล dune_env
ที่อัพเดทใหม่นี้จะมีข้อมูลความหลากหลายเป็นคอลัมน์ต่อท้ายเรียบร้อยแล้ว
เราก็จะนำไปใช้ตอบคำถามผ่านการวาดกราฟหรือวิเคราะห์สถิติได้เลย ดังตัวอย่างต่อไปนี้
Example 1: ระดับปุ๋ยคอกที่ใส่เข้าไปมีผลกระทบต่อดัชนีความหลากหลายของพืชหรือไม่
dune_env %>%
ggplot(aes(x = Manure, y = shannon)) +
geom_point() +
geom_smooth(se = F)
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
Example 2: จำนวนชนิดของพืชแตกต่างกันตามวิธีการจัดการพื้นที่หรือไม่
dune_env %>%
ggplot(aes(x = Management, y = richness)) +
geom_boxplot()
จากข้อมูล bird_comm.csv ด้านบน
เราจะเพิ่มเติมข้อมูลสิ่งแวดล้อมของนกเหล่านี้ ในไฟล์ bird_env.csv
ซึ่งประกอบด้วยข้อมูลเพิ่มเติมดังต่อไปนี้
Veg_type = vegetation type (ชนิดของสังคมพืช)
Elevation = ความสูงจากระดับทะเล
Tree_diversity = ความหลากหลายของไม้ต้น
3.1 อ่านไฟล์ bird_env.csv เข้าสู่โปรแกรม
3.2 คำนวณ species richness ของแต่ละ site
3.3 คำนวณ Shannon’s index ของแต่ละ site
3.4 เพิ่มคอลัมน์ species richness และ Shannon’s index เข้าไปใน bird_env
3.5 วาดกราฟเพื่อตรวจสอบว่า diversity ของนกเกี่ยวข้องกับ elevation หรือไม่
หัวข้อนี้เป็นหัวข้อที่อาจจะเข้าใจยากสักนิดหนึ่ง เพราะค่า beta diversity ไม่ใช่การนับเหมือน alpha หรือ gamma diversity แต่เป็นการคำนวณ ความแตกต่างขององค์ประกอบชนิด ระหว่าง sampling unit ซึ่งนักนิเวศวิทยาแต่ละท่านก็ได้นิยามไว้หลากหลายมาก (ตัวอย่างเพิ่มเติม ที่เปเปอร์ของ Koleff et al. 2003) เราจะเริ่มลองพิจารณาจากตัวอย่างง่าย ๆ ที่เราได้เริ่มไว้ด้านบนกันก่อน
sample_mat
## sp_a sp_b sp_c sp_d sp_e sp_f
## site1 2 5 0 0 0 0
## site2 0 3 1 2 1 0
## site3 0 0 0 0 4 10
จากข้อมูลของ sample_mat เราสามารถคำนวณ beta diversity
เพื่อหาความแตกต่างกันระหว่าง site โดยใช้วิธีของ Whittaker (คนคิดเรื่องนี้เป็นคนแรก
ใช้รหัสย่อ \(\beta_{w}\))
ซึ่งมีสูตรคำนวณคือ
\[ \beta_{w} = \frac{S}{\bar{\alpha}} - 1 \]
โดย S คือ จำนวนชนิดทั้งหมดที่พบใน 2 แปลง และ \(\bar{\alpha}\) คือจำนวนชนิดเฉลี่ยต่อแปลง เราสามารถใช้คำสั่งคำนวณได้ดังต่อไปนี้
sample_beta_w <- betadiver(sample_mat, method = "w")
sample_beta_w
## site1 site2
## site2 0.6666667
## site3 1.0000000 0.6666667
จากวิธีข้างต้น จะเห็นได้ว่า ความแตกต่างระหว่าง site1-site2 และ site2-site3 นั้นเท่ากัน แม้ว่าจำนวนต้นจะไม่เท่ากัน หากเราต้องการนำจำนวนต้นหรือจำนวนตัวมาใช้ประกอบการคำนวณ เราสามารถใช้วิธีการคำนวณ distance (ความแตกต่าง) มาแทนได้ ตัวอย่างเช่นเราสามารถใช้ Bray-Curtis Distance มาหาความแตกต่างระหว่าง 2 แปลงได้ โดยมีสูตรคำนวณดังนี้
\[ d_{jk} = \frac{\sum|x_{ij}-x_{ik}|}{\sum(x_{ij}+x_{ik})} \]
โดยที่ \(d_{jk}\) คือความแตกต่างขององค์ประกอบชนิดระหว่างแปลง j และ k โดยด้านบนเอาบนจำนวนตัวของแต่ละชนิดมาลบกันและบวกรวมทุกชนิด และ ตัวหาร เอาจำนวนตัวของแต่ละชนิดมาบวกกันและบวกรวมกันทุกชนิด จะเห็นว่าอะไรที่คำนวณเยอะ ๆ แบบนี้เหมาะยิ่งนักกับการให้คอมพิวเตอร์คำนวณให้เรา ตามโค้ดด้านล่างนี้
sample_beta_bray <- vegdist(sample_mat)
sample_beta_bray
## site1 site2
## site2 0.5714286
## site3 1.0000000 0.9047619
หลังจากที่คำนวณ beta diversity ได้แล้ว เราก็สามารถนำค่าที่ได้มาวาดกราฟต่อได้ โดยแบบแรกจะใช้ heatmap เพื่อแสดงความเหมือนหรือความแตกต่างรายคู่ โดยเราจะทำให้เห็นทั้งสองวิธีคือ
1- วิธีของ Whittaker (พิจารณาเฉพาะการพบหรือไม่พบ)
autoplot(sample_beta_w) +
labs(title = "Whittaker's Beta Diversity")
## Scale for y is already present.
## Adding another scale for y, which will replace the existing scale.
2- วิธีของ Bray-Curtis (พิจารณาจำนวนต้น จำนวนตัวด้วย)
autoplot(sample_beta_bray) +
labs(title = "Bray-Curtis")
## Scale for y is already present.
## Adding another scale for y, which will replace the existing scale.
อีกวิธีที่นิยมกันมากในวงการคือ การนำข้อมูลที่ได้มาทำ ordination หรือ เรียงลำดับใหม่ในมิติที่ลดรูปลงทางคณิตศาสตร์ เพื่อให้สามารถทำความเข้าใจได้ง่ายขึ้น โดยหนึ่งในวิธีที่ได้รับความนิยมมากที่สุดก็คือ principal component analysis (PCA) ซึ่งจะขออนุญาตไม่ลงหลักการใน workshop แต่ละสาธิตวิธีการคำนวณและแสดงผลดังนี้
sample_pca <- prcomp(sample_beta_bray)
autoplot(sample_pca, label = T, point = F)
สิ่งที่ควรได้จากการอ่านกราฟนี้คือ
แต่ละจุดคือ sampling unit ของเรา
ระยะห่างระหว่างจุด คือ ความแตกต่างขององค์ประกอบชนิด ระหว่าง sampling unit = ยิ่งแตกต่าง จุดยิ่งห่างกัน
% ที่อยู่ตรงแกนคือ ปริมาณ variance ภายในข้อมูลที่ได้รับการอธิบายในการคำนวณนี้ ในกรณีนี้ 2 แกนรวมกันได้ 78.9 + 21.1 = 100% ก็คือ อธิบายได้ทุกอย่างในข้อมูลนี้เลย (เพราะข้อมูลมันไม่ใหญ่มากนั่นเอง)
เรามาลองดูข้อมูลของสังคมพืชสันทรายกันบ้าง
#Calculate beta diversity
dune_beta_bray <- vegdist(dune_comm)
#Perform PCA
dune_pca <- prcomp(dune_beta_bray)
#Visualize results
autoplot(dune_pca, label = T)
PCA ของข้อมูลนี้อธิบาย Variance ได้รวมกัน 47.89+24.15 = 72.04% ซึ่งถือว่าดีเลยทีเดียว จะเห็นว่าบางจุด (เช่น 12,13) อยู่ใกล้กัน แสดงว่าองค์ประกอบชนิดคล้ายคลึงมากกว่าจุดที่ไกลออกไป
นอกจากนี้เรายังสามารถนำข้อมูล environment มาช่วย highlight ผล PCA ให้อ่านง่ายและได้ข้อมูลมากขึ้นอีกด้วย เช่นเราสามารถระบายสีแต่ละจุดตามวิธีการจัดการพื้นที่ได้ดังนี้
autoplot(dune_pca, colour = "Management", data = dune_env, frame = T)
จากข้อมูลนก bird_comm ด้านบน ให้ทุกท่านลองศึกษา beta diversity โดยดำเนินการต่อไปนี้
3.1 คำนวณ beta diversity ด้วยวิธีที่ท่านชอบ (Whittaker หรือ Bray-Curtis)
3.2 แสดงผล beta diversity ด้วย PCA ที่ให้สีตามชนิดของสังคมพืช
(Veg_type)
ใน 3.5 ชั่วโมงที่ผ่านมา เราได้เรียนรู้ไอเดียและโค้ดต่าง ๆ ค่อนข้างเยอะ ในเวลาที่ไม่มากนัก หวังว่าอย่างน้อยที่สุดผู้เรียนทุกท่านจะได้เห็นแนวทางการทำงานทางด้านความหลากหลายต่อไปในอนาคตและจะได้มีโอกาสพัฒนาทักษะเพิ่มเติมได้ต่อไปครับ หากมีข้อสงสัยเพิ่มเติม สามารถติดต่อได้ที่ ekaphan.k@ku.th