Skip to main content

R Tips 03: ยุติปัญหา Dependency Hell และติดตั้งแพ็กเกจติดสปีดด้วย rig, pak และ CRAN Time Travel

r
r-tip
pak
rig
devops
reproducibility
หมดปัญหาลงแพ็กเกจเต่าคลาน ขาด System Libraries และโค้ดพังข้ามปี ด้วยคู่หู r-lib/pak และ r-lib/rig พร้อมความลับการทำ CRAN Time Travel ย้อนเวลากลับไปดึงแพ็กเกจในอดีตได้ในบรรทัดเดียว
Published

4 พฤศจิกายน 2569

เวลาที่เราให้ AI ช่วยเขียนสคริปต์ R หรือไปโคลนโปรเจกต์จาก GitHub มาใช้งาน ปัญหาคลาสสิกที่กวนใจที่สุดมักไม่ใช่เรื่องการเขียนโค้ดตรรกะทางสถิติ แต่คือ “Dependency Hell”

เรามักคุ้นเคยกับคำสั่งพื้นฐานอย่าง install.packages() แต่เมื่อทำงานกับโปรเจกต์จริง คำสั่งนี้มักเผยข้อจำกัดหลายอย่าง:

  1. ทำงานแบบ Single-thread เต่าคลาน: ดาวน์โหลดและคอมไพล์แพ็กเกจทีละตัวตามลำดับ หากต้องติดตั้งโมเดลใหญ่ๆ อย่าง tidymodels หรือ tidyverse อาจต้องนั่งรอนาน 10–20 นาที
  2. ไม่เช็ก System Libraries ระดับ OS: ลงแพ็กเกจสายภูมิสารสนเทศ (GIS) อย่าง sf หรือ terra แล้วพังทันทีเพราะขาด GDAL, GEOS หรือ PROJ บนเครื่อง หรือลงแพ็กเกจต่อเน็ตแล้วขาด libcurl / libxml2
  3. ปัญหา DLL File Lock บน Windows: พยายามอัปเดตแพ็กเกจที่กำลังเปิดใช้งานอยู่ใน R Session แล้วโปรแกรมฟ้องว่าไม่สามารถเขียนทับไฟล์ .dll ได้
  4. โค้ดเก่าพังข้ามปี (Bit rot): สคริปต์ที่เคยรันผ่านเมื่อปีก่อน พอเปิดมารันวันนี้กลับพัง เพราะแพ็กเกจเวอร์ชันใหม่มีการเปลี่ยนแปลง Breaking Changes

วันนี้เราจะมาปลดล็อกระบบนิเวศน์ยุคใหม่ของ R ที่ถูกสร้างขึ้นมาเพื่อแก้ปัญหานี้โดยเฉพาะ ด้วยการจับคู่ r-lib/pak, เทคนิค CRAN Time Travel, และ CLI tool ระดับ OS อย่าง r-lib/rig ครับ!


1. r-lib/pak: ตัวจัดการแพ็กเกจยุคใหม่ที่เร็วกว่า 5–10 เท่า

แพ็กเกจ pak (พัฒนาโดยทีม r-lib ของ Posit) ไม่ได้เป็นเพียงแค่ตัวลงแพ็กเกจสำรอง แต่ถูกออกแบบมาให้เป็น Next-generation Package Manager ของภาษา R

[install.packages() แบบเดิม]
  CRAN -> ดาวน์โหลดทีละตัว -> คอมไพล์ทีละตัว (Single thread) -> ไม่ตรวจ OS Dependencies

──────────────────────────────────────────────────────────────────────────

[r-lib/pak ยุคใหม่]
  CRAN / Bioc / GitHub / Local
        │
        ▼ (Parallel HTTP/2 Download & Multi-core Build)
  ┌─────────────────────────────────────────────────────────────┐
  │ pak Resolution Engine (SAT Solver ตรวจสอบ Dependency ชนกัน)    │
  └──────────────────────────────┬──────────────────────────────┘
                                 │
        ┌────────────────────────┴────────────────────────┐
        ▼                                                 ▼
  Auto System Requirements                        Isolated Worker Process
  (ตรวจจับ & ติดตั้ง GDAL, PROJ, etc.)             (หมดปัญหา DLL Lock บน Windows)

1.1 ติดตั้งและใช้งานแบบ Universal Syntax

pak รวบรวมแหล่งดาวน์โหลดทั้งหมด (CRAN, Bioconductor, GitHub, Local Directory) มาไว้ในคำสั่งเดียว ไม่ต้องสลับไปใช้ BiocManager::install() หรือ remotes::install_github() อีกต่อไป:

# ติดตั้ง pak ครั้งแรก (ทำเพียงครั้งเดียว)
install.packages("pak")

# 1. ติดตั้งแพ็กเกจจาก CRAN ปกติ
pak::pkg_install("tidyverse")

# 2. ติดตั้งจากหลายแหล่งพร้อมกันในคำสั่งเดียว:
# CRAN + Bioconductor + GitHub
pak::pkg_install(c("sf", "bioc::DESeq2", "r-lib/mirai"))

# 3. ติดตั้งจาก GitHub เฉพาะ Pull Request หรือ Commit หรือ Tag
pak::pkg_install("tidyverse/dplyr#1234")    # จาก PR #1234
pak::pkg_install("tidyverse/dplyr@v1.1.0")  # จาก Tag v1.1.0

1.2 ความลับที่ 1: ส่องผังความสัมพันธ์ด้วย pkg_deps_tree()

เคยสงสัยไหมว่า ก่อนที่เราจะกดลงแพ็กเกจสักตัว มันจะลากเอาแพ็กเกจลูก (Dependencies) ตัวไหนติดมาด้วยบ้าง?

pak มีฟังก์ชันที่แสดงโครงสร้างต้นไม้ (Dependency Tree) ออกมาให้ดูอย่างชัดเจนผ่าน Console:

# แสดงโครงสร้างต้นไม้ของ Dependencies ทั้งหมดแบบลำดับชั้น
pak::pkg_deps_tree("tidymodels")

นอกจากนี้ หากสงสัยว่า “ทำไม R ถึงต้องลงแพ็กเกจ X ด้วย มันถูกดึงมาจากตัวไหน?” สามารถใช้คำสั่ง:

# ตรวจสอบว่าทำไม tidymodels ถึงต้องการแพ็กเกจ rlang
pak::pkg_deps_explain("tidymodels", "rlang")

1.3 ความลับที่ 2: ระบบ Auto System Requirements ตรวจจับสเปก OS ให้อัตโนมัติ

นี่คือฟีเจอร์ที่ช่วยชีวิตผู้ใช้ R บน Linux และ macOS มากที่สุด โดยเฉพาะคนที่ทำงานกับแพ็กเกจอย่าง sf, terra, units, curl, xml2:

# เช็กว่าแพ็กเกจ sf ต้องการไลบรารีระบบ (System Libraries) อะไรบ้างใน OS ของคุณ
pak::pkg_sysreqs("sf")

เมื่อคุณสั่ง pak::pkg_install("sf") บนเครื่อง Linux (เช่น Ubuntu / Debian / Fedora) หากระบบตรวจพบว่าขาด libgdal-dev หรือ libproj-dev ตัว pak จะดึงคำสั่ง apt-get หรือ dnf มาเสนอให้รันทันที (หรือถ้ามีสิทธิ์ sudo มันจะติดตั้งให้อัตโนมัติ) หมดปัญหาคอมไพล์ไม่ผ่านเพราะหาเฮดเดอร์ C/C++ ไม่เจอ!


1.4 ความลับที่ 3: Isolated Sub-process (แก้ปัญหา DLL Lock บน Windows)

บน Windows หากคุณกำลังเปิดใช้งาน library ใดอยู่ แล้วต้องการอัปเดตแพ็กเกจนั้น install.packages() มักจะ Error ทันที เพราะ Windows จะล็อกไฟล์ .dll ที่กำลังถูกโหลดในหน่วยความจำ

pak แก้ปัญหานี้ด้วยการสร้าง Isolated Worker Sub-process แยกต่างหากในการดาวน์โหลดและ Unpack ไฟล์ เมื่อเสร็จแล้วจึงสลับโฟลเดอร์ในระดับไฟล์ซิสเต็มอย่างปลอดภัย ทำให้คุณสามารถสั่งอัปเดตแพ็กเกจได้โดยไม่ต้องปิดและเปิดโปรแกรม R ใหม่


2. เกร็ดลับระดับ Pro: เดินทางข้ามเวลาด้วย CRAN Time Travel (Posit P3M)

หลายคนอาจเคยพึ่งพาบริการ MRAN (Microsoft R Application Network) ในอดีต แต่หลังจากที่ Microsoft ยุติบริการดังกล่าวไปเมื่อปี 2023 โลกของ R ก็มีฮีโร่ตัวใหม่เข้ามาแทนที่ นั่นคือ Posit Public Package Manager (P3M) (packagemanager.posit.co)

2.1 ย้อนเวลาไปวันไหนก็ได้ในอดีต (Snapshot by Date)

สมมติว่าคุณต้องไปตรวจงานวิจัย หรือรันโค้ดเก่าที่เพื่อนร่วมทีมเขียนไว้เมื่อวันที่ 15 พฤษภาคม 2025 แล้วพบว่ารันกับแพ็กเกจปัจจุบันไม่ผ่านเนื่องจากมีฟังก์ชันที่ถูก Deprecated ไปแล้ว

คุณสามารถสั่งให้ R “ย้อนเวลากลับไปดึง CRAN ณ วันนั้น” ได้ทันทีในบรรทัดเดียว:

# 1. ล็อก Repository ให้เป็น snapshot ณ วันที่ 15 พฤษภาคม 2025
options(repos = c(CRAN = "https://packagemanager.posit.co/cran/2025-05-15"))

# 2. ใช้ pak ติดตั้งแพ็กเกจตามปกติ
# แพ็กเกจทุกตัวที่ลง รวมถึง Dependencies ทั้งหมด จะถูกตรึงไว้ที่เวอร์ชันของวันนั้น 100%!
pak::pkg_install("dplyr")
Tipความยอดเยี่ยมของ Snapshot Date

การระบุวันที่ใน URL ของ P3M ช่วยให้เราได้สภาพแวดล้อมที่สืบย้อนผลได้ (Reproducible Environment) ทันทีในระดับคำสั่ง โดยไม่จำเป็นต้องมีไฟล์ renv.lock มาก่อนตั้งแต่ต้น


3. r-lib/rig: The R Installation Manager คู่หูระดับ OS

หาก pak คือราชาแห่งการจัดการแพ็กเกจ rig (github.com/r-lib/rig) ก็คือผู้พิทักษ์การจัดการตัวโปรแกรม R ในระดับระบบปฏิบัติการ

3.1 ทำไมต้องมี rig?

สำหรับ Data Scientist หรือนักวิจัยที่ต้อง: - ทดสอบแพ็กเกจหรือโค้ดกับ R เวอร์ชันเก่า (เช่น 4.2, 4.3) และเวอร์ชันล่าสุด (เช่น 4.4, 4.5) - สลับเวอร์ชัน R ไปมาโดยไม่ต้อง Uninstall ตัวเก่าทิ้ง - จัดการแยก Library ประจำแต่ละเวอร์ชันออกจากกันอย่างเด็ดขาด

rig ถูกพัฒนาด้วยภาษา Rust สามารถใช้งานได้เหมือนกับ nvm (Node.js) หรือ pyenv (Python) บน Windows, macOS และ Linux

# ดูรายชื่อเวอร์ชัน R ที่ติดตั้งอยู่ในเครื่อง
rig list

# ติดตั้ง R เวอร์ชันใหม่ล่าสุด หรือเวอร์ชันเฉพาะ
rig add release
rig add 4.3.3

# สลับเวอร์ชัน R หลักของเครื่องในพริบตา
rig default 4.4

# เปิด RStudio โดยใช้เอนจินของ R เวอร์ชันที่ต้องการ
rig rstudio 4.3.3

3.2 ความว้าว: Linux Pre-compiled Binaries ใน 2 วินาที

จุดเด่นที่สุดของการใช้ rig คือ เมื่อติดตั้ง R ผ่าน rig ระบบจะกำหนดค่าเริ่มต้นให้ R ชี้ไปยัง Posit Public Package Manager (P3M) Binary Mirror ให้ทันที

  • แบบเดิมบน Linux: ทุกครั้งที่สั่งลง tidyverse หรือ ggplot2 ระบบต้องคอมไพล์ C++ จากซอร์สโค้ด ใช้เวลานาน 15–30 นาที
  • เมื่อใช้ rig + pak: R จะดาวน์โหลด Pre-compiled Binary สำหรับ Linux Distribution นั้นๆ ลงเสร็จภายใน 2–5 วินาที เหมือนกับการลงบน Windows หรือ macOS!

4. ตารางเปรียบเทียบหมัดต่อหมัด

คุณสมบัติ install.packages() (Base R) r-lib/pak ยุคใหม่ rig + pak (Full Stack)
ความเร็วในการดาวน์โหลด ช้า (Single connection) เร็วมาก (HTTP/2 ขนาน) เร็วมาก (HTTP/2 ขนาน)
การรองรับ Multi-source แยกคำสั่งตามแหล่ง CRAN / Bioc / GitHub ในคำสั่งเดียว CRAN / Bioc / GitHub ในคำสั่งเดียว
ตรวจสอบ System Requirements ❌ ไม่ตรวจ (ต้องลงมือเอง) ✅ ตรวจจับและสั่งลงให้อัตโนมัติ ✅ ตรวจจับและสั่งลงให้อัตโนมัติ
การแก้ปัญหา DLL Lock (Windows) ❌ ล็อกบ่อย ต้องรีสตาร์ท R ✅ ทำงานผ่าน Sub-process ไม่ติดล็อก ✅ ทำงานผ่าน Sub-process ไม่ติดล็อก
Linux Binary Packages ❌ ต้อง Compile จากซอร์สโค้ด ⚠️ ขึ้นอยู่กับการตั้งค่า Repo ✅ Pre-compiled Binaries อัตโนมัติ
การสลับเวอร์ชัน R (OS Level) ❌ สลับยาก ต้องแก้ PATH เอง ❌ จัดการเฉพาะระดับแพ็กเกจ ✅ สลับได้ใน 1 วินาที (rig default)
CRAN Time Travel รองรับผ่าน repos url รองรับเต็มรูปแบบร่วมกับ P3M รองรับและตั้งค่าให้อัตโนมัติ

5. สรุป Workflow แนะนำสำหรับปี 2026

เพื่อให้ชีวิตการเขียนโค้ด R ของคุณราบรื่นและไม่ต้องปวดหัวกับ Dependency อีกต่อไป แนะนำแนวทางปฏิบัติดังนี้:

  1. ระดับเครื่อง (OS): ติดตั้ง rig ไว้เป็นเครื่องมือจัดการ R ประจำเครื่อง เพื่อให้ง่ายต่อการติดตั้งและสลับเวอร์ชัน R
  2. ระดับ Session: ใช้ pak::pkg_install() แทน install.packages() เสมอเพื่อประหยัดเวลาและตัดปัญหาไลบรารีระบบ
  3. ระดับความยั่งยืนของโค้ด (Reproducibility): หากโปรเจกต์ไม่ได้ใช้ renv ให้ระบุ Snapshot Date ของ P3M ไว้ที่ส่วนหัวของสคริปต์ เพื่อให้ทุกคนที่นำโค้ดไปรันในอนาคตได้แพ็กเกจชุดเดียวกันเสมอ
Noteแหล่งข้อมูลและคลังโค้ดต้นน้ำ