Writing
RData ScienceAgricultureAPI

ประเมินระยะเปียกใบ (Leaf Wetness Duration) ด้วย R

ประเมินระยะเปียกใบ (Leaf Wetness Duration) ด้วย R

ประเมินระยะเปียกใบ (Leaf Wetness Duration) ด้วย R

การหาระยะเปียกใบ (Leaf Wetness Duration - LWD) ย้อนหลังจากพิกัด (Latitude/Longitude) เป็นไอเดียที่ดีมากครับ โดยเฉพาะในงานด้านการเกษตรและการพยากรณ์โรคพืช

แต่ต้องขออธิบายตามความเป็นจริงก่อนว่า โดยทั่วไปแล้ว ข้อมูลระยะเปียกใบมักจะไม่มีการตรวจวัดโดยตรงในสถานีตรวจอากาศสาธารณะ แต่ในทางอุตุนิยมวิทยาเกษตร เราสามารถ “ประเมิน” (Estimate) ระยะเปียกใบได้จากข้อมูลสภาพอากาศพื้นฐาน เช่น ปริมาณน้ำฝน (Precipitation) และ ความชื้นสัมพัทธ์ (Relative Humidity - RH) ครับ

หลักการประเมิน (Empirical Model):

ใบพืชจะถือว่า “เปียก” ในชั่วโมงนั้นๆ ก็ต่อเมื่อ:

ดังนั้น ผมจึงออกแบบ R function โดยดึงข้อมูลรายชั่วโมงจาก API ฟรีของ Open-Meteo (ซึ่งเก็บข้อมูลสภาพอากาศย้อนหลังทั่วโลกได้ดีมาก) แล้วนำมาคำนวณหาระยะเปียกใบรวมในแต่ละวันให้ครับ


💻 R Function สำหรับประเมินระยะเปียกใบเบื้องต้น

ก่อนใช้งาน ต้องติดตั้ง package ที่จำเป็นก่อนนะครับ โดยรันคำสั่ง:

install.packages(c("httr", "jsonlite", "dplyr", "lubridate"))
# โหลด Libraries ที่จำเป็น
library(httr)
library(jsonlite)
library(dplyr)
library(lubridate)

#' ฟังก์ชันดึงและคำนวณข้อมูลระยะเปียกใบ (Leaf Wetness Duration) รายวัน
#' 
#' @param lat ละติจูด (เช่น 14.0205)
#' @param lon ลองจิจูด (เช่น 100.7299)
#' @param start_date วันที่เริ่มต้น รูปแบบ "YYYY-MM-DD"
#' @param end_date วันที่สิ้นสุด รูปแบบ "YYYY-MM-DD"
#' @param rh_threshold เกณฑ์ความชื้นสัมพัทธ์ที่ทำให้เกิดน้ำค้าง (ค่าเริ่มต้น 90%)
#' @return Dataframe สรุประยะเวลาเปียกใบ (ชั่วโมง/วัน)
get_leaf_wetness <- function(lat, lon, start_date, end_date, rh_threshold = 90) {
  
  # 1. สร้าง URL เพื่อดึงข้อมูล API ของ Open-Meteo Historical Data
  url <- paste0(
    "https://archive-api.open-meteo.com/v1/archive?",
    "latitude=", lat,
    "&longitude=", lon,
    "&start_date=", start_date,
    "&end_date=", end_date,
    "&hourly=precipitation,relative_humidity_2m",
    "&timezone=auto"
  )
  
  # 2. ดึงข้อมูลผ่าน API
  response <- GET(url)
  
  if (status_code(response) != 200) {
    stop("เกิดข้อผิดพลาดในการดึงข้อมูล กรุณาตรวจสอบพิกัด อินเทอร์เน็ต หรือวันที่")
  }
  
  # แปลง JSON เป็น Data Frame
  data_json <- fromJSON(content(response, "text", encoding = "UTF-8"))
  
  # 3. จัดการข้อมูลรายชั่วโมง
  hourly_data <- data.frame(
    # Open-Meteo ส่งเวลามาในรูปแบบ "2024-01-01T00:00"
    time = ymd_hm(data_json$hourly$time),
    precipitation = data_json$hourly$precipitation,
    relative_humidity = data_json$hourly$relative_humidity_2m
  )
  
  # 4. ประเมินระยะเปียกใบ (Leaf Wetness) ในแต่ละชั่วโมง
  # ให้ชั่วโมงนั้นมีค่า = 1 หากมีฝนตก หรือ ความชื้นสัมพัทธ์สูงกว่าเกณฑ์
  hourly_data <- hourly_data %>%
    mutate(
      is_wet = ifelse(
        (!is.na(precipitation) & precipitation > 0) | 
        (!is.na(relative_humidity) & relative_humidity >= rh_threshold),
        1, 0 # 1 คือเปียก, 0 คือแห้ง
      ),
      date = as.Date(time) # สกัดเฉพาะวันที่เพื่อใช้ออกรายงาน
    )
  
  # 5. สรุปผลเป็นรายวัน (ชั่วโมงเปียกใบรวมใน 1 วัน)
  daily_lwd <- hourly_data %>%
    group_by(date) %>%
    summarise(
      leaf_wetness_hours = sum(is_wet, na.rm = TRUE),
      avg_humidity_percent = round(mean(relative_humidity, na.rm = TRUE), 2),
      total_precip_mm = sum(precipitation, na.rm = TRUE)
    )
  
  return(daily_lwd)
}

# ==========================================
# 📌 ตัวอย่างการใช้งาน (Example Usage)
# ==========================================
# สมมติใช้พิกัดรังสิต ปทุมธานี ช่วงวันที่ 1 - 7 มีนาคม 2026

# lat_example <- 14.0205
# lon_example <- 100.7299
# result <- get_leaf_wetness(
#   lat = lat_example, 
#   lon = lon_example, 
#   start_date = "2026-03-01", 
#   end_date = "2026-03-07"
# )

# print(result)

📊 สิ่งที่คุณจะได้จาก Function นี้

Dataframe ที่ Return กลับมาจะมีข้อมูลตามนี้ครับ:

ข้อควรระวัง: ฟังก์ชันนี้ประเมินระยะเปียกใบจาก “สภาพอากาศระดับมหภาค (Macroclimate)” แต่ในแปลงปลูกจริง (Microclimate) ระยะเวลาที่ใบแห้งหรือเปียกอาจแตกต่างกันตามความหนาแน่นของทรงพุ่มหรือทิศทางลม หากคุณต้องการความแม่นยำสูงระดับร้อยเปอร์เซ็นต์ อาจต้องปรับตัวแปร rh_threshold ให้เหมาะสมกับชนิดพืชของคุณดูครับ (บางงานวิจัยใช้ที่ 85% หรือ 92%)


การทำ Advanced Leaf Wetness Duration สำหรับนาข้าว

การประเมินระยะเปียกใบใหัแม่นยำระดับนำไปใช้งานจริงกับ “นาข้าว” นั้น มีความท้าทายเฉพาะตัวครับ เนื่องจากข้าวเป็นพืชที่มีทรงพุ่มหนาแน่นและปลูกในสภาพน้ำขัง (Paddy field) การใช้แค่เกณฑ์ความชื้นสัมพัทธ์ (RH) แบบพื้นฐานอาจคลาดเคลื่อนได้ง่าย นี่คือข้อมูลเจาะลึกและแนวทางยกระดับความแม่นยำครับ

🌾 ทำไม “ข้าว” ถึงประเมินระยะเปียกใบได้ยากกว่าพืชอื่น?

🛠️ 3 แนวทางในการสร้าง Model ให้แม่นยำขึ้น (จากง่ายไปยาก)

งานวิจัยระดับสากลแนะนำแนวทางในการประเมิน LWD ไว้ 3 ระดับ ดังนี้ครับ:

1. การปรับปรุงสมการเชิงประจักษ์ (Improved Empirical Model)

เป็นวิธีที่นำไปเขียนใน R Function ได้ง่ายที่สุดและให้ผลลัพธ์ดีขึ้นอย่างก้าวกระโดด งานวิจัยระบุว่าการใช้แค่ฝนและ RH > 90% ยังไม่พอ ต้องเพิ่มตัวแปร “ลม” และ “แสงแดด” ที่เป็นตัวการทำให้น้ำระเหย (Drying factors) เข้าไปเป็นเงื่อนไขด้วย

2. แบบจำลองสมดุลพลังงาน (Physical Model / Penman-Monteith)

นี่คือมาตรฐานขั้นสูง (Gold Standard) ทางอุตุนิยมวิทยาฟิสิกส์ แทนที่จะใช้การตั้งเงื่อนไข (If-Else) วิธีนี้จะคำนวณ Latent Heat Flux (LE) หรือพลังงานที่ใช้ในการควบแน่นและระเหยของน้ำบนผิวใบโดยตรงผ่านสมการ:

LE = [-\Delta R_n + 1200(e_s - e_a) / (r_a + r_b)] / (\Delta + \gamma)

แบบจำลองนี้แม่นยำมากเพราะอิงตามหลักฟิสิกส์ของการเกิดน้ำค้าง แต่ข้อเสียคือ “ต้องการข้อมูลสภาพอากาศที่ละเอียดมาก” เช่น ค่าความต้านทานอากาศของทรงพุ่มข้าว (r_a, r_b) และรังสีสุทธิ (R_n)

3. การใช้ Machine Learning (Data-Driven Model)

เปเปอร์วิจัยในช่วง 5-6 ปีที่ผ่านมา (เช่น งานวิจัย LWD ในเกาหลีใต้) หันมาใช้ AI อย่าง Random Forest หรือ Deep Neural Networks กันหมดแล้วครับ


Logic ที่แม่นยำขึ้นสำหรับ Improved Empirical Model

ใบจะเปียก ก็ต่อเมื่อ (มีฝนตก) หรือ (ความชื้นสูง + อุณหภูมิใกล้จุดน้ำค้าง + ลมสงบ + ไม่มีแดดจัด)

ใบข้าวจะถูกประเมินว่า “เปียก (Wet = 1)” ในชั่วโมงนั้นๆ ก็ต่อเมื่อเข้าเงื่อนไขใดเงื่อนไขหนึ่งต่อไปนี้:


💻 R Function: Advanced Leaf Wetness Duration

# โหลด Libraries ที่จำเป็น
library(httr)
library(jsonlite)
library(dplyr)
library(lubridate)

#' ฟังก์ชันประเมินระยะเปียกใบขั้นสูง (Advanced LWD) สำหรับนาข้าว

get_advanced_lwd <- function(lat, lon, start_date, end_date) {
  
  # 1. กำหนด URL ดึงข้อมูล 6 ตัวแปร (ฝน, ความชื้น, อุณหภูมิ, จุดน้ำค้าง, ลม, รังสีดวงอาทิตย์)
  url <- paste0(
    "https://archive-api.open-meteo.com/v1/archive?",
    "latitude=", lat,
    "&longitude=", lon,
    "&start_date=", start_date,
    "&end_date=", end_date,
    "&hourly=precipitation,relative_humidity_2m,temperature_2m,dew_point_2m,wind_speed_10m,shortwave_radiation",
    "&timezone=auto"
  )
  
  # 2. ดึงข้อมูล API
  response <- GET(url)
  if (status_code(response) != 200) {
    stop("เกิดข้อผิดพลาดในการเชื่อมต่อ API กรุณาตรวจสอบข้อมูลนำเข้า")
  }
  
  data_json <- fromJSON(content(response, "text", encoding = "UTF-8"))
  
  # 3. จัดรูป Dataframe
  hourly_data <- data.frame(
    time = ymd_hm(data_json$hourly$time),
    precip = data_json$hourly$precipitation,
    rh = data_json$hourly$relative_humidity_2m,
    temp = data_json$hourly$temperature_2m,
    dew = data_json$hourly$dew_point_2m,
    wind = data_json$hourly$wind_speed_10m,
    solar = data_json$hourly$shortwave_radiation
  )
  
  # 4. ประเมิน LWD ตามตรรกะ Improved Empirical Model
  hourly_data <- hourly_data %>%
    mutate(
      dew_depression = temp - dew, # คำนวณส่วนต่างอุณหภูมิและจุดน้ำค้าง
      is_wet = case_when(
        # เงื่อนไขที่ 1: ฝนตก
        !is.na(precip) & precip > 0 ~ 1,
        # เงื่อนไขที่ 2: น้ำค้าง (ชื้นสูง + อุณหภูมิใกล้จุดน้ำค้าง + ลมสงบ + ไม่มีแดด)
        (!is.na(rh) & rh >= 85) & 
        (!is.na(dew_depression) & dew_depression <= 2.0) & 
        (!is.na(wind) & wind < 3.0) & 
        (!is.na(solar) & solar < 50) ~ 1,
        # นอกนั้นถือว่าแห้ง
        TRUE ~ 0 
      ),
      date = as.Date(time)
    )
  
  # 5. สรุปผลเป็นรายวัน
  daily_summary <- hourly_data %>%
    group_by(date) %>%
    summarise(
      lwd_hours = sum(is_wet, na.rm = TRUE),
      total_precip_mm = sum(precip, na.rm = TRUE),
      avg_temp_c = round(mean(temp, na.rm = TRUE), 1),
      avg_rh_percent = round(mean(rh, na.rm = TRUE), 1)
    )
  
  return(daily_summary)
}

# ==========================================
# 📌 ตัวอย่างการใช้งาน
# ==========================================
# พิกัด รังสิต ปทุมธานี
# df_result <- get_advanced_lwd(14.0205, 100.7299, "2026-03-01", "2026-03-10")
# print(df_result)

ข้อดีของโมเดลนี้:

ตัวเลขเกณฑ์ต่างๆ (เช่น ลม < 3, ความชื้น ≥ 85) เป็นค่ากลางจากเปเปอร์วิจัยที่ใช้ได้ดีในเขตร้อนชื้นครับ แต่ถ้าคุณมีข้อมูลสภาพแวดล้อมเฉพาะเจาะจงในแปลง ก็สามารถเข้าไปแก้ตัวเลขใน case_when ได้เลย ลองเอาไปปรับใช้กับฟาร์มของคุณดูนะครับ 🌱

เอกสารอ้างอิง