Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	Commit 
							
							·
						
						d4d1ca8
	
1
								Parent(s):
							
							a50dc6d
								
Initialization
Browse files- .DS_Store +0 -0
- .env.example +2 -0
- .gitignore +7 -0
- README.md +190 -14
- app.py +325 -0
- data/.DS_Store +0 -0
- data/data_1.csv +49 -0
- data/data_2.csv +66 -0
- data/data_3.csv +0 -0
- data/data_3_1.csv +51 -0
- requirements.txt +24 -0
- scripts/anomaly.py +193 -0
- scripts/classify.py +446 -0
- scripts/data_cleansing.py +42 -0
- scripts/forecast.py +59 -0
- scripts/label_suggestion.py +104 -0
- scripts/summarize.py +73 -0
    	
        .DS_Store
    ADDED
    
    | Binary file (8.2 kB). View file | 
|  | 
    	
        .env.example
    ADDED
    
    | @@ -0,0 +1,2 @@ | |
|  | |
|  | 
|  | |
| 1 | 
            +
            ## Copy this file to .env and set your Hugging Face token
         | 
| 2 | 
            +
            HF_TOKEN=
         | 
    	
        .gitignore
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            .env
         | 
| 2 | 
            +
            outputs/
         | 
| 3 | 
            +
            __pycache__/
         | 
| 4 | 
            +
            scripts/__pycache__
         | 
| 5 | 
            +
            .venv/
         | 
| 6 | 
            +
            .python-version
         | 
| 7 | 
            +
            README.md
         | 
    	
        README.md
    CHANGED
    
    | @@ -1,14 +1,190 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # OMS Analyze — Prototype
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            โปรเจกต์นี้เป็นแอปพลิเคชันต้นแบบสำหรับวิเคราะห์ข้อมูลการดับไฟฟ้า (OMS - Outage Management System) โดยใช้ AI และ Machine Learning เพื่อสรุป สืบหาความผิดปกติ พยากรณ์ และจำแนกสาเหตุ
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            แอปสร้างด้วย Gradio สำหรับใช้งานผ่านเว็บเบราว์เซอร์ และรองรับการอัปโหลดไฟล์ CSV เพื่อวิเคราะห์
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## การติดตั้งและรัน
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ### ข้อกำหนด
         | 
| 10 | 
            +
            - Python 3.12.9
         | 
| 11 | 
            +
            - ติดตั้งแพ็คเกจจาก `requirements.txt`:
         | 
| 12 | 
            +
              ```
         | 
| 13 | 
            +
              pip install -r requirements.txt
         | 
| 14 | 
            +
              ```
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ### การตั้งค่าสภาพแวดล้อมด้วย pyenv (แนะนำ)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ตัวอย่างคำสั่งที่ผมใช้เพื่อเตรียม environment บน macOS (แนะนำใช้ pyenv เพื่อจัดการเวอร์ชัน Python):
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            ```
         | 
| 21 | 
            +
            cd /Users/peace/Documents/projects/huggingface/AI-OMS-Analyze
         | 
| 22 | 
            +
            pyenv install 3.12.9
         | 
| 23 | 
            +
            pyenv local 3.12.9
         | 
| 24 | 
            +
            /Users/$(whoami)/.pyenv/versions/3.12.9/bin/python -m venv .venv
         | 
| 25 | 
            +
            source .venv/bin/activate
         | 
| 26 | 
            +
            python -m pip install --upgrade pip setuptools wheel
         | 
| 27 | 
            +
            python -m pip install -r requirements.txt
         | 
| 28 | 
            +
            ```
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            หมายเหตุ:
         | 
| 31 | 
            +
            - ผมคอมเมนต์ `prophet` ใน `requirements.txt` เพราะการติดตั้งจะพยายามคอมไพล์ CmdStan (C++ build) ซึ่งใช้เวลานานและมักต้องการเครื่องมือเพิ่มเติม (Xcode command line tools). ถ้าต้องการติดตั้ง `prophet` ให้ uncomment แล้วเตรียมเครื่องมือ build.
         | 
| 32 | 
            +
            - ผมอัปเดต `fsspec` และ `openai` เป็นเวอร์ชันที่มีอยู่ใน PyPI เพื่อให้ pip หาแพ็กเกจเจอได้
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            - สำหรับการใช้ Hugging Face Router (สำหรับ LLM ใน Summarization และ Classification): ตั้งค่า `HF_TOKEN` ในไฟล์ `.env` (ดู `.env.example`)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            ### Windows (ใช้ pyenv-win)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            ถ้าคุณใช้ Windows ผมแนะนำติดตั้ง `pyenv-win` เพื่อจัดการเวอร์ชัน Python (หรือใช้ Python ที่ติดตั้งผ่าน Chocolatey / Microsoft Store แล้วสร้าง venv ตามปกติ)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            1) ติดตั้ง pyenv-win (PowerShell - Run as Administrator แนะนำ)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            ```
         | 
| 43 | 
            +
            # ผ่าน PowerShell (Admin)
         | 
| 44 | 
            +
            Invoke-WebRequest -UseBasicParsing -Uri "https://pyenv.run" -OutFile "pyenv-win-install.ps1"
         | 
| 45 | 
            +
            Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
         | 
| 46 | 
            +
            .\n+\pyenv-win-install.ps1
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            # หรือ ติดตั้งด้วย Scoop (ถ้ามี scoop)
         | 
| 49 | 
            +
            scoop install pyenv
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            แอปแบ่งเป็นแท็บหลัก (UI) ดังนี้ — คำอธิบายสรุปการใช้งานและไฟล์ผลลัพธ์ที่ระบบจะสร้างในโฟลเดอร์ `outputs/`:
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            ### 1. Upload & Preview
         | 
| 54 | 
            +
            - วัตถุประสงค์: อัปโหลดไฟล์ CSV และตรวจสอบตัวอย่างข้อมูล
         | 
| 55 | 
            +
            - วิธีใช้:
         | 
| 56 | 
            +
              1. คลิก "Upload CSV" แล้วเลือกไฟล์ (ตัวอย่าง: `data/data_1.csv`, `data/data_3.csv`)
         | 
| 57 | 
            +
              2. ดูตัวอย่าง 10 แถวแรกและตรวจสอบชนิดของคอลัมน์
         | 
| 58 | 
            +
            - ผลลัพธ์: preview เท่านั้น — การรันฟังก์ชันวิเคราะห์จะสร้างผลลัพธ์ลงใน `outputs/`
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            ### 2. Summarization
         | 
| 61 | 
            +
            - วัตถุประสงค์: สร้างสรุปภาษาธรรมชาติสำหรับแต่ละเหตุการณ์หรือชุดข้อมูล
         | 
| 62 | 
            +
            - วิธีใช้:
         | 
| 63 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 64 | 
            +
              2. ระบุแถวที่ต้องการสรุป (เว้นว่าง = ทั้งหมด; ห���ือระบุ index เช่น `0,1,2`)
         | 
| 65 | 
            +
              3. ถ้าต้องการใช้ LLM ให้เปิด "Use Hugging Face Router" และตั้ง `HF_TOKEN` ใน `.env`
         | 
| 66 | 
            +
              4. เลือกระดับรายละเอียด (brief / medium / detailed) แล้วคลิก "Generate Summaries"
         | 
| 67 | 
            +
            - ผลลัพธ์: ไฟล์ `outputs/summaries_from_ui.csv` (UI run) หรือ `outputs/summaries.csv` (batch export)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            ### 3. Anomaly Detection
         | 
| 70 | 
            +
            - วัตถุประสงค์: ตรวจหาเหตุการณ์ผิดปกติด้วย ML (IsolationForest, LOF)
         | 
| 71 | 
            +
            - วิธีใช้:
         | 
| 72 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 73 | 
            +
              2. เลือก algorithm: `both` (IsolationForest + LOF), `iso`, หรือ `lof`
         | 
| 74 | 
            +
              3. ปรับค่า contamination (0.01–0.2, default 0.05)
         | 
| 75 | 
            +
              4. คลิก "Run Anomaly Detection"
         | 
| 76 | 
            +
            - ผลลัพธ์: `outputs/anomalies_from_ui.csv` (UI run) หรือ `outputs/anomalies.csv` (batch). รายการ suspects จะถูกบันทึกเป็น `outputs/ntl_suspects.csv` ถ้ามีการตรวจจับ
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            ### 4. Forecasting
         | 
| 79 | 
            +
            - วัตถุประสงค์: พยากรณ์จำนวนเหตุการณ์หรือ downtime ในอนาคต
         | 
| 80 | 
            +
            - วิธีใช้:
         | 
| 81 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 82 | 
            +
              2. เลือก metric: `count` หรือ `downtime_minutes`
         | 
| 83 | 
            +
              3. ตั้ง horizon (7–90 วัน, default 14)
         | 
| 84 | 
            +
              4. คลิก "Run Forecast"
         | 
| 85 | 
            +
            - ผลลัพธ์: `outputs/forecast_count_from_ui.csv`, `outputs/forecast_downtime_minutes_from_ui.csv` (UI run) หรือ batch outputs `outputs/forecast_count.csv`, `outputs/forecast_downtime_minutes.csv`
         | 
| 86 | 
            +
              (หากต้องการความแม่นยำมากขึ้น ให้ติดตั้ง `prophet==1.1.7`)
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            ### 5. Classification
         | 
| 89 | 
            +
            - วัตถุประสงค์: จำแนกสาเหตุของเหตุการณ์ (root-cause classification)
         | 
| 90 | 
            +
            - วิธีใช้:
         | 
| 91 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 92 | 
            +
              2. (Optional) เปิด "Run weak-labeling using HF" เพื่อให้ LLM สร้าง weak labels (`HF_TOKEN` ต้องถูกตั้ง)
         | 
| 93 | 
            +
              3. (Optional) เลือก "Run GridSearch" สำหรับ tuning
         | 
| 94 | 
            +
              4. คลิก "Train Classifier"
         | 
| 95 | 
            +
            - ผลลัพธ์: โมเดลและผลลัพธ์จะถูกบันทึกลง `outputs/`, ตัวอย่างไฟล์:
         | 
| 96 | 
            +
              - `outputs/rf_cause_pipeline.joblib`
         | 
| 97 | 
            +
              - `outputs/predictions_cause.csv`
         | 
| 98 | 
            +
              - ถ้ามีหลายโมเดล: `outputs/predictions_gb_CauseType.csv`, `outputs/predictions_mlp_CauseType.csv`, `outputs/predictions_rf_CauseType.csv`
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            python -m pip install --upgrade pip setuptools wheel
         | 
| 101 | 
            +
            python -m pip install -r requirements.txt
         | 
| 102 | 
            +
            ```
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            หมายเหตุ สำหรับ Windows:
         | 
| 105 | 
            +
            - บางแพ็กเกจ (เช่น `geopandas`, `fiona`, `pyproj`, `shapely`) มี native dependencies (GDAL, PROJ) — การใช้ Miniforge/Conda จะทำให้ง่ายกว่า (conda-forge)
         | 
| 106 | 
            +
            - `prophet` มักจะต้องการการติดตั้ง CmdStan/cmdstanpy ล่วงหน้า และอาจจะซับซ้อนบน Windows — พิจารณาใช้ WSL2 หรือ conda สำหรับงานนี้
         | 
| 107 | 
            +
             | 
| 108 | 
            +
             | 
| 109 | 
            +
            ### รันแอป
         | 
| 110 | 
            +
            ```
         | 
| 111 | 
            +
            python app.py
         | 
| 112 | 
            +
            ```
         | 
| 113 | 
            +
            แอปจะรันที่ `http://127.0.0.1:7860` (หรือปรับ port ด้วย `--server.port PORT`)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            ### โครงสร้างไฟล์
         | 
| 116 | 
            +
            - `data/data.csv`: ไฟล์ข้อมูลตัวอย่าง
         | 
| 117 | 
            +
            - `scripts/`: โมดูล Python สำหรับแต่ละฟีเจอร์
         | 
| 118 | 
            +
            - `outputs/`: ไฟล์ผลลัพธ์จากการวิเคราะห์
         | 
| 119 | 
            +
            - `app.py`: แอป Gradio หลัก
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            ## คู่มือการใช้งาน
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            แอปแบ่งเป็นแท็บต่างๆ ดังนี้:
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            ### 1. Upload & Preview
         | 
| 126 | 
            +
            - **วัตถุประสงค์**: อัปโหลดไฟล์ CSV และดูตัวอย่างข้อมูล
         | 
| 127 | 
            +
            - **วิธีใช้**:
         | 
| 128 | 
            +
              1. คลิก "Upload CSV" เลือกไฟล์ CSV (เช่น `data/data.csv`)
         | 
| 129 | 
            +
              2. แสดงตัวอย่าง 10 แถวแรกในตาราง HTML
         | 
| 130 | 
            +
            - **หมายเหตุ**: ใช้สำหรับตรวจสอบข้อมูลก่อนวิเคราะห์
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            ### 2. Summarization
         | 
| 133 | 
            +
            - **วัตถุประสงค์**: สร้างสรุปภาษาธรรมชาติสำหรับเหตุการณ์ดับไฟฟ้า
         | 
| 134 | 
            +
            - **วิธีใช้**:
         | 
| 135 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 136 | 
            +
              2. เลือกแถวที่ต้องการสรุป (เว้นว่าง = ทั้งหมด, หรือใส่ index เช่น `0,1,2`)
         | 
| 137 | 
            +
              3. เลือก "Use Hugging Face Router" ถ้ามี `HF_TOKEN` (ใช้ LLM สำหรับสรุปละเอียด)
         | 
| 138 | 
            +
              4. เลือก verbosity: brief/medium/detailed
         | 
| 139 | 
            +
              5. คลิก "Generate Summaries"
         | 
| 140 | 
            +
              6. ดูผลสรุปในตาราง และ download ไฟล์ `summaries_from_ui.csv`
         | 
| 141 | 
            +
            - **ฟีเจอร์**: รองรับ fallback เป็น rule-based summary ถ้าไม่มี HF token
         | 
| 142 | 
            +
            - **ผลลัพธ์**: CSV กับคอลัมน์ EventNumber, OutageDateTime, Summary
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            ### 3. Anomaly Detection
         | 
| 145 | 
            +
            - **วัตถุประสงค์**: ตรวจหาเหตุการณ์ผิดปกติโดยใช้ Machine Learning
         | 
| 146 | 
            +
            - **วิธีใช้**:
         | 
| 147 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 148 | 
            +
              2. เลือก algorithm: both (IsolationForest + LOF), iso, หรือ lof
         | 
| 149 | 
            +
              3. ปรับ contamination (0.01-0.2, ค่าเริ่มต้น 0.05)
         | 
| 150 | 
            +
              4. คลิก "Run Anomaly Detection"
         | 
| 151 | 
            +
              5. ดูผลในตาราง (รวมคอลัมน์ anomaly flags และ explanations)
         | 
| 152 | 
            +
              6. Download ไฟล์ `anomalies_from_ui.csv`
         | 
| 153 | 
            +
            - **ฟีเจอร์**: Feature engineering (duration, load, affected customers, etc.), z-score explanations
         | 
| 154 | 
            +
            - **ผลลัพธ์**: CSV กับคอลัมน์ anomaly scores และ textual explanations
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            ### 4. Forecasting
         | 
| 157 | 
            +
            - **วัตถุประสงค์**: พยากรณ์จำนวนเหตุการณ์หรือ downtime ในอนาคต
         | 
| 158 | 
            +
            - **วิธีใช้**:
         | 
| 159 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 160 | 
            +
              2. เลือก metric: count (จำนวนเหตุการณ์) หรือ downtime_minutes
         | 
| 161 | 
            +
              3. ปรับ horizon (7-90 วัน, ค่าเริ่มต้น 14)
         | 
| 162 | 
            +
              4. คลิก "Run Forecast"
         | 
| 163 | 
            +
              5. ดูผลในตาราง (แสดง actual ล่าสุด + forecast)
         | 
| 164 | 
            +
              6. Download ไฟล์ `forecast_{metric}_from_ui.csv`
         | 
| 165 | 
            +
            - **ฟีเจอร์**: ใช้ Prophet ถ้าติดตั้งได้, มิฉะนั้นใช้ naive forecast
         | 
| 166 | 
            +
            - **ผลลัพธ์**: CSV กับคอลัมน์ date และ predicted values
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            ### 5. Classification
         | 
| 169 | 
            +
            - **วัตถุประสงค์**: จัดประเภทสาเหตุของเหตุการณ์ (Root-Cause Classification)
         | 
| 170 | 
            +
            - **วิธีใช้**:
         | 
| 171 | 
            +
              1. อัปโหลดไฟล์ CSV
         | 
| 172 | 
            +
              2. เลือก "Run weak-labeling using HF" ถ้าต้องการใช้ LLM เสริม labels (ต้องมี HF_TOKEN)
         | 
| 173 | 
            +
              3. เลือก "Run GridSearch" สำหรับ hyperparameter tuning (ช้ากว่า)
         | 
| 174 | 
            +
              4. คลิก "Train Classifier"
         | 
| 175 | 
            +
              5. ดู classification report ใน textbox
         | 
| 176 | 
            +
              6. Download โมเดล `rf_cause_pipeline.joblib` และ predictions `predictions_cause.csv`
         | 
| 177 | 
            +
            - **ฟีเจอร์**: Feature engineering, RandomForest pipeline, optional GridSearchCV, weak-labeling ด้วย HF Router
         | 
| 178 | 
            +
            - **ผลลัพธ์**: โมเดล trained และ predictions CSV
         | 
| 179 | 
            +
             | 
| 180 | 
            +
            ## หมายเหตุ
         | 
| 181 | 
            +
            - เป็น prototype: ฟีเจอร์อาจไม่สมบูรณ์หรือปรับปรุงได้
         | 
| 182 | 
            +
            - สำหรับ deployment บน Hugging Face Spaces: อัปโหลดโค้ดและตั้งค่า HF_TOKEN ใน Secrets
         | 
| 183 | 
            +
            - ข้อมูลตัวอย่าง: `data/data.csv` มีคอลัมน์เช่น EventNumber, OutageDateTime, CauseType, etc.
         | 
| 184 | 
            +
            - ถ้ามีปัญหา: ตรวจสอบ console สำหรับ errors และ ensure Python environment ถูกต้อง
         | 
| 185 | 
            +
             | 
| 186 | 
            +
            ## การพัฒนาเพิ่มเติม
         | 
| 187 | 
            +
            - เพิ่ม interactive maps สำหรับ anomalies
         | 
| 188 | 
            +
            - SHAP explanations สำหรับ models
         | 
| 189 | 
            +
            - Human-in-the-loop สำหรับ weak labels
         | 
| 190 | 
            +
            - Alerting และ real-time processing
         | 
    	
        app.py
    ADDED
    
    | @@ -0,0 +1,325 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import gradio as gr
         | 
| 2 | 
            +
            import pandas as pd
         | 
| 3 | 
            +
            from pathlib import Path
         | 
| 4 | 
            +
            from scripts.summarize import summarize_events
         | 
| 5 | 
            +
            from scripts.data_cleansing import cleanse_data
         | 
| 6 | 
            +
            from dotenv import load_dotenv
         | 
| 7 | 
            +
            import os
         | 
| 8 | 
            +
            import numpy as np
         | 
| 9 | 
            +
            import joblib
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ROOT = Path(__file__).resolve().parents[0]
         | 
| 12 | 
            +
            load_dotenv(ROOT / '.env')
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            def preview_csv(file_obj):
         | 
| 16 | 
            +
                try:
         | 
| 17 | 
            +
                    df = pd.read_csv(file_obj.name, dtype=str)
         | 
| 18 | 
            +
                    return df.head(10).to_html(index=False)
         | 
| 19 | 
            +
                except Exception as e:
         | 
| 20 | 
            +
                    return f"Error reading file: {e}"
         | 
| 21 | 
            +
             | 
| 22 | 
            +
             | 
| 23 | 
            +
            def parse_row_selection(df, rows_text: str):
         | 
| 24 | 
            +
                if not rows_text:
         | 
| 25 | 
            +
                    return df
         | 
| 26 | 
            +
                idx = []
         | 
| 27 | 
            +
                for token in rows_text.split(','):
         | 
| 28 | 
            +
                    token = token.strip()
         | 
| 29 | 
            +
                    if token.isdigit():
         | 
| 30 | 
            +
                        idx.append(int(token))
         | 
| 31 | 
            +
                return df.iloc[idx]
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             | 
| 34 | 
            +
            with gr.Blocks() as demo:
         | 
| 35 | 
            +
                gr.Markdown("# OMS Analyze — Prototype")
         | 
| 36 | 
            +
                with gr.Tabs():
         | 
| 37 | 
            +
                    # Upload & Preview tab
         | 
| 38 | 
            +
                    with gr.TabItem('Upload & Preview'):
         | 
| 39 | 
            +
                        gr.Markdown("**อัปโหลด & แสดงตัวอย่าง**: อัปโหลดไฟล์ CSV เพื่อแสดงตัวอย่างข้อมูล ใช้ algorithm ทำความสะอาดข้อมูล (ลบข้อมูลซ้ำ, จัดการค่าที่หายไป) และเปรียบเทียบข้อมูลเดิมกับข้อมูลที่ทำความสะอาด ดาวน์โหลด CSV ที่ทำความสะอาดแล้ว")
         | 
| 40 | 
            +
                        csv_up = gr.File(label='Upload CSV (data.csv)')
         | 
| 41 | 
            +
                        with gr.Row():
         | 
| 42 | 
            +
                            remove_dup = gr.Checkbox(label='Remove Duplicates', value=False)
         | 
| 43 | 
            +
                            missing_handling = gr.Radio(choices=['drop','impute_mean','impute_median','impute_mode'], value='drop', label='Missing Values Handling')
         | 
| 44 | 
            +
                            apply_clean = gr.Button('Apply Cleansing')
         | 
| 45 | 
            +
                        with gr.Tabs():
         | 
| 46 | 
            +
                            with gr.TabItem('Original Data'):
         | 
| 47 | 
            +
                                original_preview = gr.Dataframe(label='Original Data Preview')
         | 
| 48 | 
            +
                            with gr.TabItem('Cleansed Data'):
         | 
| 49 | 
            +
                                cleansed_preview = gr.Dataframe(label='Cleansed Data Preview')
         | 
| 50 | 
            +
                                download_cleansed = gr.File(label='Download Cleansed CSV')
         | 
| 51 | 
            +
                        clean_status = gr.Textbox(label='Cleansing Status', interactive=False)
         | 
| 52 | 
            +
                        
         | 
| 53 | 
            +
                        def initial_preview(file):
         | 
| 54 | 
            +
                            if file is None:
         | 
| 55 | 
            +
                                return pd.DataFrame(), pd.DataFrame(), "Upload a file"
         | 
| 56 | 
            +
                            df = pd.read_csv(file.name, dtype=str)
         | 
| 57 | 
            +
                            return df.head(100), pd.DataFrame(), "File uploaded, apply cleansing if needed"
         | 
| 58 | 
            +
                        
         | 
| 59 | 
            +
                        def apply_cleansing(file, remove_duplicates, missing_strategy):
         | 
| 60 | 
            +
                            if file is None:
         | 
| 61 | 
            +
                                return pd.DataFrame(), "No file", None
         | 
| 62 | 
            +
                            try:
         | 
| 63 | 
            +
                                df = pd.read_csv(file.name, dtype=str)
         | 
| 64 | 
            +
                                df_clean, orig_shape, clean_shape = cleanse_data(df, remove_duplicates, missing_strategy)
         | 
| 65 | 
            +
                                status = f"Original: {orig_shape[0]} rows, {orig_shape[1]} cols → Cleaned: {clean_shape[0]} rows, {clean_shape[1]} cols"
         | 
| 66 | 
            +
                                # Save cleansed data for download
         | 
| 67 | 
            +
                                out_file = ROOT / 'outputs' / 'cleansed_data.csv'
         | 
| 68 | 
            +
                                out_file.parent.mkdir(exist_ok=True)
         | 
| 69 | 
            +
                                df_clean.to_csv(out_file, index=False, encoding='utf-8-sig')
         | 
| 70 | 
            +
                                return df_clean.head(100), status, str(out_file)
         | 
| 71 | 
            +
                            except Exception as e:
         | 
| 72 | 
            +
                                return pd.DataFrame(), f"Error: {e}", None
         | 
| 73 | 
            +
                        
         | 
| 74 | 
            +
                        csv_up.change(fn=initial_preview, inputs=csv_up, outputs=[original_preview, cleansed_preview, clean_status])
         | 
| 75 | 
            +
                        apply_clean.click(fn=apply_cleansing, inputs=[csv_up, remove_dup, missing_handling], outputs=[cleansed_preview, clean_status, download_cleansed])
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    # Summarization tab
         | 
| 78 | 
            +
                    with gr.TabItem('Summarization'):
         | 
| 79 | 
            +
                        gr.Markdown("**สรุปเหตุการณ์**: สร้างสรุปข้อความสำหรับเหตุการณ์ไฟฟ้าล้ม เลือกแถวเฉพาะ, ระดับรายละเอียด และเลือกใช้ AI (Hugging Face) เพื่อเพิ่มความละเอียด ดาวน์โหลด CSV สรุป")
         | 
| 80 | 
            +
                        csv_in = gr.File(label='Upload CSV (data.csv)')
         | 
| 81 | 
            +
                        with gr.Row():
         | 
| 82 | 
            +
                            rows = gr.Textbox(label='Rows (comma-separated indexes) or empty = all', placeholder='e.g. 0,1,2')
         | 
| 83 | 
            +
                            use_hf = gr.Checkbox(label='Use Generative AI', value=False)
         | 
| 84 | 
            +
                            verbosity = gr.Radio(choices=['analyze','recommend'], value='analyze', label='Summary Type', interactive=True)
         | 
| 85 | 
            +
                            run_btn = gr.Button('Generate Summaries', interactive=True)
         | 
| 86 | 
            +
                        with gr.Row():
         | 
| 87 | 
            +
                            model_selector = gr.Dropdown(
         | 
| 88 | 
            +
                                choices=[
         | 
| 89 | 
            +
                                    'meta-llama/Llama-3.1-8B-Instruct:novita',
         | 
| 90 | 
            +
                                    'meta-llama/Llama-4-Scout-17B-16E-Instruct:novita',
         | 
| 91 | 
            +
                                    'Qwen/Qwen3-VL-235B-A22B-Instruct:novita',
         | 
| 92 | 
            +
                                    'deepseek-ai/DeepSeek-R1:novita'
         | 
| 93 | 
            +
                                ],
         | 
| 94 | 
            +
                                value='meta-llama/Llama-3.1-8B-Instruct:novita',
         | 
| 95 | 
            +
                                label='GenAI Model',
         | 
| 96 | 
            +
                                interactive=True,
         | 
| 97 | 
            +
                                visible=False
         | 
| 98 | 
            +
                            )
         | 
| 99 | 
            +
                        out = gr.Dataframe(headers=['EventNumber','OutageDateTime','Summary'])
         | 
| 100 | 
            +
                        status = gr.Textbox(label='Status', interactive=False)
         | 
| 101 | 
            +
                        download = gr.File(label='Download summaries')
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                        def run_summarize(file, rows_text, use_hf_flag, verbosity_level):
         | 
| 104 | 
            +
                            print(f"Debug: file={file}, rows_text={rows_text}, use_hf_flag={use_hf_flag}, verbosity_level={verbosity_level}")
         | 
| 105 | 
            +
                            if file is None:
         | 
| 106 | 
            +
                                return pd.DataFrame([], columns=['EventNumber','OutageDateTime','Summary']), 'No file provided', None
         | 
| 107 | 
            +
                            df = pd.read_csv(file.name, dtype=str)
         | 
| 108 | 
            +
                            df_sel = parse_row_selection(df, rows_text)
         | 
| 109 | 
            +
                            model = 'meta-llama/Llama-3.1-8B-Instruct:novita'  # default
         | 
| 110 | 
            +
                            res = summarize_events(df_sel, use_hf=use_hf_flag, verbosity=verbosity_level, model=model)
         | 
| 111 | 
            +
                            out_df = pd.DataFrame(res)
         | 
| 112 | 
            +
                            out_file = ROOT / 'outputs' / 'summaries_from_ui.csv'
         | 
| 113 | 
            +
                            out_file.parent.mkdir(exist_ok=True)
         | 
| 114 | 
            +
                            out_df.to_csv(out_file, index=False, encoding='utf-8-sig')
         | 
| 115 | 
            +
                            status_text = f"Summaries generated: {len(out_df)} rows. HF used: {use_hf_flag}"
         | 
| 116 | 
            +
                            return out_df, status_text, str(out_file)
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                        def update_model_visibility(use_hf_flag):
         | 
| 119 | 
            +
                            return gr.update(visible=use_hf_flag, interactive=use_hf_flag)
         | 
| 120 | 
            +
                        
         | 
| 121 | 
            +
                        use_hf.change(fn=update_model_visibility, inputs=use_hf, outputs=model_selector)
         | 
| 122 | 
            +
                        
         | 
| 123 | 
            +
                        run_btn.click(fn=run_summarize, inputs=[csv_in, rows, use_hf, verbosity], outputs=[out, status, download])
         | 
| 124 | 
            +
                    with gr.TabItem('Anomaly Detection'):
         | 
| 125 | 
            +
                        gr.Markdown("**ตรวจจับความผิดปกติ**: ตรวจจับเหตุการณ์ไฟฟ้าล้มที่ผิดปกติโดยใช้ algorithm การเรียนรู้ของเครื่อง (Isolation Forest, Local Outlier Factor, Autoencoder) ตั้งระดับการปนเปื้อนและดาวน์โหลดผลลัพธ์พร้อมธงความผิดปกติ")
         | 
| 126 | 
            +
                        csv_in_anom = gr.File(label='Upload CSV for Anomaly')
         | 
| 127 | 
            +
                        with gr.Row():
         | 
| 128 | 
            +
                            alg = gr.Radio(choices=['both','iso','lof','autoencoder'], value='both', label='Algorithm')
         | 
| 129 | 
            +
                            contamination = gr.Slider(minimum=0.01, maximum=0.2, value=0.05, step=0.01, label='Contamination')
         | 
| 130 | 
            +
                            run_anom = gr.Button('Run Anomaly Detection')
         | 
| 131 | 
            +
                        anom_out = gr.Dataframe()
         | 
| 132 | 
            +
                        anom_status = gr.Textbox(label='Anomaly Status', interactive=False)
         | 
| 133 | 
            +
                        anom_download = gr.File(label='Download anomalies CSV')
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                        def run_anomaly_ui(file, algorithm, contamination):
         | 
| 136 | 
            +
                            if file is None:
         | 
| 137 | 
            +
                                return pd.DataFrame(), 'No file provided', None
         | 
| 138 | 
            +
                            from scripts.anomaly import detect_anomalies
         | 
| 139 | 
            +
                            df = pd.read_csv(file.name, dtype=str)
         | 
| 140 | 
            +
                            res = detect_anomalies(df, contamination=contamination, algorithm=algorithm)
         | 
| 141 | 
            +
                            out_file = ROOT / 'outputs' / 'anomalies_from_ui.csv'
         | 
| 142 | 
            +
                            out_file.parent.mkdir(exist_ok=True)
         | 
| 143 | 
            +
                            res.to_csv(out_file, index=False, encoding='utf-8-sig')
         | 
| 144 | 
            +
                            status = f"Anomaly detection done. Rows: {len(res)}. Flags: {res['final_flag'].sum()}"
         | 
| 145 | 
            +
                            return res, status, str(out_file)
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                        run_anom.click(fn=run_anomaly_ui, inputs=[csv_in_anom, alg, contamination], outputs=[anom_out, anom_status, anom_download])
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                    # Forecasting tab
         | 
| 150 | 
            +
                    with gr.TabItem('Forecasting'):
         | 
| 151 | 
            +
                        gr.Markdown("**พยากรณ์**: พยากรณ์จำนวนเหตุการณ์หรือเวลาหยุดทำงานในอนาคตโดยใช้การวิเคราะห์อนุกรมเวลา (Prophet) เลือกเมตริกและช่วงพยากรณ์ ดาวน์โหลด CSV พยากรณ์")
         | 
| 152 | 
            +
                        csv_in_fc = gr.File(label='Upload CSV for Forecast')
         | 
| 153 | 
            +
                        with gr.Row():
         | 
| 154 | 
            +
                            metric_fc = gr.Radio(choices=['count','downtime_minutes'], value='count', label='Metric')
         | 
| 155 | 
            +
                            horizon = gr.Slider(minimum=7, maximum=90, value=14, step=1, label='Horizon (days)')
         | 
| 156 | 
            +
                            run_fc = gr.Button('Run Forecast')
         | 
| 157 | 
            +
                        fc_out = gr.Dataframe()
         | 
| 158 | 
            +
                        fc_status = gr.Textbox(label='Forecast Status', interactive=False)
         | 
| 159 | 
            +
                        fc_download = gr.File(label='Download forecast CSV')
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                        def run_forecast_ui(file, metric, horizon_days):
         | 
| 162 | 
            +
                            if file is None:
         | 
| 163 | 
            +
                                return pd.DataFrame(), 'No file provided', None
         | 
| 164 | 
            +
                            from scripts.forecast import prepare_timeseries, run_forecast
         | 
| 165 | 
            +
                            df = pd.read_csv(file.name, dtype=str)
         | 
| 166 | 
            +
                            ts, fcst = run_forecast(df, metric=metric, periods=int(horizon_days))
         | 
| 167 | 
            +
                            out_file = ROOT / 'outputs' / f'forecast_{metric}_from_ui.csv'
         | 
| 168 | 
            +
                            out_file.parent.mkdir(exist_ok=True)
         | 
| 169 | 
            +
                            fcst.to_csv(out_file, index=False, encoding='utf-8-sig')
         | 
| 170 | 
            +
                            status = f"Forecast produced: {len(fcst)} rows (horizon {horizon_days} days)."
         | 
| 171 | 
            +
                            display_df = pd.concat([ts.tail(30).rename(columns={'y':'actual'}).set_index('ds'), fcst.set_index('ds')], axis=1).reset_index()
         | 
| 172 | 
            +
                            return display_df, status, str(out_file)
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                        run_fc.click(fn=run_forecast_ui, inputs=[csv_in_fc, metric_fc, horizon], outputs=[fc_out, fc_status, fc_download])
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                    # Classification tab
         | 
| 177 | 
            +
                    with gr.TabItem('Classification'):
         | 
| 178 | 
            +
                        gr.Markdown("**จำแนกประเภท**: ฝึกโมเดลการเรียนรู้ของเครื่องเพื่อจำแนกสาเหตุของไฟฟ้าล้ม เลือกประเภทโมเดล (Random Forest, Gradient Boosting, MLP), เปิดใช้งาน weak labeling หรือ grid search ดาวน์โหลดโมเดลที่ฝึกแล้วและการทำนาย")
         | 
| 179 | 
            +
                        csv_in_cls = gr.File(label='Upload CSV for Classification')
         | 
| 180 | 
            +
                        with gr.Row():
         | 
| 181 | 
            +
                            label_col = gr.Dropdown(choices=['CauseType','SubCauseType'], value='CauseType', label='Target Column')
         | 
| 182 | 
            +
                            do_weak = gr.Checkbox(label='Run weak-labeling using HF (requires HF_TOKEN)', value=False)
         | 
| 183 | 
            +
                            model_type = gr.Radio(choices=['rf','gb','mlp'], value='rf', label='Model Type')
         | 
| 184 | 
            +
                            run_cls = gr.Button('Train Classifier')
         | 
| 185 | 
            +
                        def update_hyperparams_visibility(model_choice):
         | 
| 186 | 
            +
                            rf_visible = model_choice == 'rf'
         | 
| 187 | 
            +
                            gb_visible = model_choice == 'gb'
         | 
| 188 | 
            +
                            mlp_visible = model_choice == 'mlp'
         | 
| 189 | 
            +
                            return [
         | 
| 190 | 
            +
                                gr.update(visible=rf_visible),
         | 
| 191 | 
            +
                                gr.update(visible=rf_visible),
         | 
| 192 | 
            +
                                gr.update(visible=rf_visible),
         | 
| 193 | 
            +
                                gr.update(visible=rf_visible),
         | 
| 194 | 
            +
                                gr.update(visible=gb_visible),
         | 
| 195 | 
            +
                                gr.update(visible=gb_visible),
         | 
| 196 | 
            +
                                gr.update(visible=gb_visible),
         | 
| 197 | 
            +
                                gr.update(visible=mlp_visible),
         | 
| 198 | 
            +
                                gr.update(visible=mlp_visible),
         | 
| 199 | 
            +
                                gr.update(visible=mlp_visible),
         | 
| 200 | 
            +
                            ]
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                        with gr.Accordion("Hyperparameters (Advanced)", open=False):
         | 
| 203 | 
            +
                            gr.Markdown("Adjust hyperparameters for the selected model. Defaults are set for good performance.")
         | 
| 204 | 
            +
                            rf_n_estimators = gr.Slider(minimum=50, maximum=500, value=100, step=10, label="RF: n_estimators", visible=True)
         | 
| 205 | 
            +
                            rf_max_depth = gr.Slider(minimum=5, maximum=50, value=10, step=1, label="RF: max_depth", visible=True)
         | 
| 206 | 
            +
                            rf_min_samples_split = gr.Slider(minimum=2, maximum=10, value=2, step=1, label="RF: min_samples_split", visible=True)
         | 
| 207 | 
            +
                            rf_min_samples_leaf = gr.Slider(minimum=1, maximum=5, value=1, step=1, label="RF: min_samples_leaf", visible=True)
         | 
| 208 | 
            +
                            gb_n_estimators = gr.Slider(minimum=50, maximum=500, value=100, step=10, label="GB: n_estimators", visible=False)
         | 
| 209 | 
            +
                            gb_max_depth = gr.Slider(minimum=3, maximum=20, value=3, step=1, label="GB: max_depth", visible=False)
         | 
| 210 | 
            +
                            gb_learning_rate = gr.Slider(minimum=0.01, maximum=0.3, value=0.1, step=0.01, label="GB: learning_rate", visible=False)
         | 
| 211 | 
            +
                            mlp_hidden_layer_sizes = gr.Textbox(value="(100,)", label="MLP: hidden_layer_sizes (tuple)", visible=False)
         | 
| 212 | 
            +
                            mlp_alpha = gr.Slider(minimum=0.0001, maximum=0.01, value=0.0001, step=0.0001, label="MLP: alpha", visible=False)
         | 
| 213 | 
            +
                            mlp_max_iter = gr.Slider(minimum=100, maximum=4000, value=500, step=50, label="MLP: max_iter", visible=False)
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                        model_type.change(fn=update_hyperparams_visibility, inputs=model_type, outputs=[rf_n_estimators, rf_max_depth, rf_min_samples_split, rf_min_samples_leaf, gb_n_estimators, gb_max_depth, gb_learning_rate, mlp_hidden_layer_sizes, mlp_alpha, mlp_max_iter])
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                        cls_out = gr.Textbox(label='Classification Report')
         | 
| 218 | 
            +
                        model_path_state = gr.State()
         | 
| 219 | 
            +
                        cls_download_model = gr.File(label='Download saved model')
         | 
| 220 | 
            +
                        cls_download_preds = gr.File(label='Download predictions CSV')
         | 
| 221 | 
            +
                        
         | 
| 222 | 
            +
                        # Test section
         | 
| 223 | 
            +
                        gr.Markdown("---")
         | 
| 224 | 
            +
                        gr.Markdown("**ทดสอบโมเดล**: อัปโหลดไฟล์ CSV ใหม่เพื่อทดสอบโมเดลที่ฝึกแล้ว")
         | 
| 225 | 
            +
                        test_csv = gr.File(label='Upload CSV for Testing')
         | 
| 226 | 
            +
                        run_test = gr.Button('Test Model')
         | 
| 227 | 
            +
                        test_out = gr.Dataframe(label='Test Predictions')
         | 
| 228 | 
            +
                        test_status = gr.Textbox(label='Test Status', interactive=False)
         | 
| 229 | 
            +
                        test_download = gr.File(label='Download Test Predictions')
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                        def run_classify_ui(file, label_col_choice, use_weak, model_choice, rf_n_est, rf_max_d, rf_min_ss, rf_min_sl, gb_n_est, gb_max_d, gb_lr, mlp_hls, mlp_a, mlp_mi):
         | 
| 232 | 
            +
                            if file is None:
         | 
| 233 | 
            +
                                return 'No file provided', None, None, None
         | 
| 234 | 
            +
                            from scripts.classify import train_classifier
         | 
| 235 | 
            +
                            df = pd.read_csv(file.name, dtype=str)
         | 
| 236 | 
            +
                            try:
         | 
| 237 | 
            +
                                hyperparams = {}
         | 
| 238 | 
            +
                                if model_choice == 'rf':
         | 
| 239 | 
            +
                                    hyperparams = {'n_estimators': int(rf_n_est), 'max_depth': int(rf_max_d), 'min_samples_split': int(rf_min_ss), 'min_samples_leaf': int(rf_min_sl)}
         | 
| 240 | 
            +
                                elif model_choice == 'gb':
         | 
| 241 | 
            +
                                    hyperparams = {'n_estimators': int(gb_n_est), 'max_depth': int(gb_max_d), 'learning_rate': gb_lr}
         | 
| 242 | 
            +
                                elif model_choice == 'mlp':
         | 
| 243 | 
            +
                                    import ast
         | 
| 244 | 
            +
                                    hyperparams = {'hidden_layer_sizes': ast.literal_eval(mlp_hls), 'alpha': mlp_a, 'max_iter': int(mlp_mi)}
         | 
| 245 | 
            +
                                res = train_classifier(df, label_col=label_col_choice, model_type=model_choice, hyperparams=hyperparams)
         | 
| 246 | 
            +
                                report = res.get('report','')
         | 
| 247 | 
            +
                                model_file = res.get('model_file')
         | 
| 248 | 
            +
                                preds_file = res.get('predictions_file')
         | 
| 249 | 
            +
                                # ensure returned file paths are strings for Gradio
         | 
| 250 | 
            +
                                return report, model_file, preds_file, model_file
         | 
| 251 | 
            +
                            except Exception as e:
         | 
| 252 | 
            +
                                return f'Training failed: {e}', None, None, None
         | 
| 253 | 
            +
                        
         | 
| 254 | 
            +
                        def run_test_ui(test_file, model_path):
         | 
| 255 | 
            +
                            if test_file is None:
         | 
| 256 | 
            +
                                return pd.DataFrame(), 'No test file provided', None
         | 
| 257 | 
            +
                            if model_path is None:
         | 
| 258 | 
            +
                                return pd.DataFrame(), 'No trained model available. Please train a model first.', None
         | 
| 259 | 
            +
                            try:
         | 
| 260 | 
            +
                                from scripts.classify import parse_and_features
         | 
| 261 | 
            +
                                # Load model
         | 
| 262 | 
            +
                                model_data = joblib.load(model_path)
         | 
| 263 | 
            +
                                pipeline = model_data['pipeline']
         | 
| 264 | 
            +
                                le = model_data['label_encoder']
         | 
| 265 | 
            +
                                
         | 
| 266 | 
            +
                                # Load and preprocess test data
         | 
| 267 | 
            +
                                df_test = pd.read_csv(test_file.name, dtype=str)
         | 
| 268 | 
            +
                                df_test = parse_and_features(df_test)
         | 
| 269 | 
            +
                                
         | 
| 270 | 
            +
                                # Define features (same as training)
         | 
| 271 | 
            +
                                feature_cols = ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq','OpDeviceType','Owner','Weather','EventType']
         | 
| 272 | 
            +
                                X_test = df_test[feature_cols]
         | 
| 273 | 
            +
                                
         | 
| 274 | 
            +
                                # Predict
         | 
| 275 | 
            +
                                y_pred_encoded = pipeline.predict(X_test)
         | 
| 276 | 
            +
                                y_pred = le.inverse_transform(y_pred_encoded)
         | 
| 277 | 
            +
                                
         | 
| 278 | 
            +
                                # Create output df
         | 
| 279 | 
            +
                                pred_df = df_test.copy()
         | 
| 280 | 
            +
                                pred_df['Predicted_CauseType'] = y_pred
         | 
| 281 | 
            +
                                
         | 
| 282 | 
            +
                                # Save predictions
         | 
| 283 | 
            +
                                out_file = ROOT / 'outputs' / 'test_predictions.csv'
         | 
| 284 | 
            +
                                out_file.parent.mkdir(exist_ok=True)
         | 
| 285 | 
            +
                                pred_df.to_csv(out_file, index=False, encoding='utf-8-sig')
         | 
| 286 | 
            +
                                
         | 
| 287 | 
            +
                                status = f"Test completed. Predictions for {len(pred_df)} rows."
         | 
| 288 | 
            +
                                return pred_df.head(100), status, str(out_file)
         | 
| 289 | 
            +
                            except Exception as e:
         | 
| 290 | 
            +
                                return pd.DataFrame(), f'Test failed: {e}', None
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                        run_cls.click(fn=run_classify_ui, inputs=[csv_in_cls, label_col, do_weak, model_type, rf_n_estimators, rf_max_depth, rf_min_samples_split, rf_min_samples_leaf, gb_n_estimators, gb_max_depth, gb_learning_rate, mlp_hidden_layer_sizes, mlp_alpha, mlp_max_iter], outputs=[cls_out, cls_download_model, cls_download_preds, model_path_state])
         | 
| 293 | 
            +
                        run_test.click(fn=run_test_ui, inputs=[test_csv, model_path_state], outputs=[test_out, test_status, test_download])
         | 
| 294 | 
            +
             | 
| 295 | 
            +
                    # Label Suggestion tab
         | 
| 296 | 
            +
                    with gr.TabItem('Label Suggestion'):
         | 
| 297 | 
            +
                        gr.Markdown("**แนะนำป้ายกำกับ**: แนะนำป้ายกำกับสาเหตุที่เป็นไปได้สำหรับเหตุการณ์ไฟฟ้าล้มที่ไม่รู้สาเหตุ โดยอิงจากความคล้ายกับสาเหตุที่รู้จัก ตั้งจำนวนคำแนะนำสูงสุด ดาวน์��หลด CSV คำแนะนำ")
         | 
| 298 | 
            +
                        csv_in_ls = gr.File(label='Upload CSV (defaults to data/data_3.csv)')
         | 
| 299 | 
            +
                        with gr.Row():
         | 
| 300 | 
            +
                            top_k = gr.Slider(minimum=1, maximum=5, value=1, step=1, label='Top K suggestions')
         | 
| 301 | 
            +
                            run_ls = gr.Button('Run Label Suggestion')
         | 
| 302 | 
            +
                        ls_out = gr.Dataframe()
         | 
| 303 | 
            +
                        ls_status = gr.Textbox(label='Label Suggestion Status', interactive=False)
         | 
| 304 | 
            +
                        ls_download = gr.File(label='Download label suggestions')
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                        def run_label_suggestion(file, top_k_suggest):
         | 
| 307 | 
            +
                            # delegate to scripts.label_suggestion
         | 
| 308 | 
            +
                            from scripts.label_suggestion import suggest_labels_to_file
         | 
| 309 | 
            +
                            if file is None:
         | 
| 310 | 
            +
                                default = ROOT / 'data' / 'data_3.csv'
         | 
| 311 | 
            +
                                if not default.exists():
         | 
| 312 | 
            +
                                    return pd.DataFrame(), 'No file provided and default data/data_3.csv not found', None
         | 
| 313 | 
            +
                                df = pd.read_csv(default, dtype=str)
         | 
| 314 | 
            +
                            else:
         | 
| 315 | 
            +
                                df = pd.read_csv(file.name, dtype=str)
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                            out_file = ROOT / 'outputs' / 'label_suggestions.csv'
         | 
| 318 | 
            +
                            out_df = suggest_labels_to_file(df, out_path=str(out_file), top_k=int(top_k_suggest))
         | 
| 319 | 
            +
                            status = f"Label suggestion done. Unknown rows processed: {len(out_df)}. Output: {out_file}"
         | 
| 320 | 
            +
                            return out_df, status, str(out_file) if len(out_df)>0 else None
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                        run_ls.click(fn=run_label_suggestion, inputs=[csv_in_ls, top_k], outputs=[ls_out, ls_status, ls_download])
         | 
| 323 | 
            +
             | 
| 324 | 
            +
            if __name__ == '__main__':
         | 
| 325 | 
            +
                demo.launch()
         | 
    	
        data/.DS_Store
    ADDED
    
    | Binary file (6.15 kB). View file | 
|  | 
    	
        data/data_1.csv
    ADDED
    
    | @@ -0,0 +1,49 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            Number,EventNumber,OutageDateTime,CountOfRestoStep,FirstRestoDateTime,LastRestoDateTime,FirstStepDuration,LastStepDuration,EventType,SubstationID,Feeder,OpDeviceID,OpDeviceGIStag,OpDeviceXYcoord,OpDeviceType,OpDeviceStatus,OpDevicePhase,OpVolt,OpVolt1,OpVolt2,OpDeviceSysType,Owner,FaultSysType,KnowUnknowCause,Weather,CauseType,SubCauseType,FaultDeviceType,FaultDevice,FaultDeviceCondition,Parts,DamagedParts,Manufacturer,RelayType,Relation,RelayPhase,RelayStatus,Detail,FaultDetail,SiteDetail,OpDeviceAreaID,OpDeviceSiteID,EventSiteID,AffectedAreaID,AffectedSiteID,Industrial,AffectedCustomer1,AffectedCustomer2,AffectedCustomer3,AffectedCustomer4,AffectedCustomer5,AffectedCustomer,AllStepCusXTime1,AllStepCusXTime2,AllStepCusXTime3,AllStepCusXTime4,AllStepCusXTime5,AllStepCusXTime,Capacity(kVA),Load(MW),CorrectionDetail,WorkOrderID,CreateEventDateTime,CloseEventDateTime
         | 
| 2 | 
            +
            1,5522625735,10-01-2025 10:28:00,1,10-01-2025 10:33:00,10-01-2025 10:33:00,5,5,แผนดับไฟ,KWB,KWB07,59-019156,32XFHA001805499,"702290.194109,1516163.221549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,บำรุงรักษาตามวาระ,บำรุงรักษาตามวาระอื่นๆ,หม้อแปลงจำหน่าย,,,หม้อแปลงจำหน่าย,,,,,,,,,บำรุงรักษาหม้อแปลง,C2_P,H23101,H23101,C2_P,H23101,,,,,,30,30,,,,,150,150,160,0.014288043,,1007429318,21-05-2024 21:46:02,10-01-2025 10:32:38
         | 
| 3 | 
            +
            2,5523583596,10-01-2025 10:33:00,1,10-01-2025 10:38:00,10-01-2025 10:38:00,5,5,แผนดับไฟ,KWB,KWB07,51-006725,32XFHA000029380,"702729.380109,1516737.858549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,บำรุงรักษาตามวาระ,บำรุงรักษาตามวาระอื่นๆ,หม้อแปลงจำหน่าย,,,หม้อแปลงจำหน่าย,,,,,,,,,บำรุงรักษาหม้อแปลง,C2_P,H23101,H23101,C2_P,H23101,,,,,,34,34,,,,,170,170,100,0.018150423,,1007430088,22-05-2024 08:37:11,10-01-2025 10:34:40
         | 
| 4 | 
            +
            3,5523761535,10-01-2025 10:35:00,1,10-01-2025 10:40:00,10-01-2025 10:40:00,5,5,แผนดับไฟ,KWB,KWB07,24-016273,3224XF000001242,"711060.735109,1525056.524549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,บำรุงรักษาตามวาระ,บำรุงรักษาตามวาระอื่นๆ,หม้อแปลงจำหน่าย,,,หม้อแปลงจำหน่าย,,,,,,,,,บำรุงรักษาหม้อแปลง,C2_P,H23101,H23101,C2_P,H23101,,,,,,85,85,,,,,425,425,250,0.06943619,,1007430461,22-05-2024 10:48:52,10-01-2025 10:36:02
         | 
| 5 | 
            +
            4,5579114474,10-01-2025 11:05:00,1,10-01-2025 11:10:00,10-01-2025 11:10:00,5,5,แผนดับไฟ,KWB,KWB10,KWB10F-02,32SWHA001430130,"714702.043109,1524010.689549",Drop out Fuse,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ทดสอบระบบการจ่ายไฟ,ทดสอบอื่นๆ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,.,C2_P,H23101,H23101,C2_P,H23101,,,,,,64,64,,,,,320,320,120,0.07338668,,1007885616,13-06-2024 15:19:37,10-01-2025 11:07:05
         | 
| 6 | 
            +
            5,5610738244,09-01-2025 15:48:00,1,09-01-2025 15:48:00,09-01-2025 15:48:00,0,0,แผนดับไฟ,-,-,NKP04YB-01,32CHHA000001746,"731293.435109,1418702.857549",Circuit Breaker_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14101,,,,,,,0,,,,,,0,0,0,,1007521312,27-06-2024 10:31:59,09-01-2025 15:49:05
         | 
| 7 | 
            +
            6,5632771392,09-01-2025 14:55:00,1,09-01-2025 15:00:00,09-01-2025 15:00:00,5,5,แผนดับไฟ,GUU,GUU04,GUU04R-02,32RCHA000003846,"832182.213109,1432428.503549",Recloser,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับป���ุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,เขาคิชฌกูฏ,C2_P,H03108,H03108,C2_P,H03108,,,,,2559,,2559,,,,12795,,12795,6480,0.74881445,,,08-07-2024 14:32:42,09-01-2025 15:00:36
         | 
| 8 | 
            +
            8,5696187479,09-01-2025 15:42:00,1,09-01-2025 15:43:00,09-01-2025 15:43:00,1,1,แผนดับไฟ,BAP,BAP04,BAP04VS-103,32SWHA001424800,"712262.272109,1531181.496549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บางน้ำเปรี้ยว,C2_P,H23201,H23201,C2_P,H23201,,,,,859,1756,2615,,,,859,1756,2615,15715,2.8329294,,,06-08-2024 13:38:32,09-01-2025 15:43:29
         | 
| 9 | 
            +
            9,5696187479,09-01-2025 15:42:00,1,09-01-2025 15:43:00,09-01-2025 15:43:00,1,1,แผนดับไฟ,BAP,BAP04,BAP04VS-103,32SWHA001424800,"712262.272109,1531181.496549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บางน้ำเปรี้ยว,C2_P,H23201,H23201,C2_P,H23202,,,,,817,1420,2237,,,,817,1420,2237,9485,2.8329294,,,06-08-2024 13:38:32,09-01-2025 15:43:29
         | 
| 10 | 
            +
            10,5702510021,09-01-2025 15:41:00,1,09-01-2025 15:41:00,09-01-2025 15:41:00,0,0,แผนดับไฟ,MBA,MBA05,RAB10S-10,32SWHA001411561,"737096.562109,1415463.974549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14101,,,,,622,,622,,,,0,,0,14615,2.6354336,,,08-08-2024 10:00:34,09-01-2025 15:42:20
         | 
| 11 | 
            +
            11,5702510021,09-01-2025 15:41:00,1,09-01-2025 15:41:00,09-01-2025 15:41:00,0,0,แผนดับไฟ,MBA,MBA05,RAB10S-10,32SWHA001411561,"737096.562109,1415463.974549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14201,,,,,725,,725,,,,0,,0,8580,2.6354336,,,08-08-2024 10:00:34,09-01-2025 15:42:20
         | 
| 12 | 
            +
            12,5728292708,09-01-2025 15:10:00,1,09-01-2025 15:10:00,09-01-2025 15:10:00,0,0,แผนดับไฟ,KZA,KZA05,KZA05VS-102,32SWHA000002670,"865079.515109,1340225.456549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,เกาะช้าง,C2_P,H04401,H04401,C2_P,H04401,,,,,286,,286,,,,0,,0,1190,0.14538371,,1007632768,18-08-2024 00:01:08,09-01-2025 15:11:30
         | 
| 13 | 
            +
            14,5816619933,09-01-2025 15:16:00,1,09-01-2025 15:16:00,09-01-2025 15:16:00,0,0,แผนดับไฟ,-,-,APB104YB-01,32CHHA000000693,"709219.130109,1451836.395549",Circuit Breaker_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,แหลมฉบัง,C2_P,H22101,H22101,C2_P,H22101,,,,,,,0,,,,,,0,0,0,,,23-09-2024 10:24:39,09-01-2025 15:17:28
         | 
| 14 | 
            +
            15,5817699872,09-01-2025 15:39:00,1,09-01-2025 15:39:00,09-01-2025 15:39:00,0,0,แผนดับไฟ,BAP,BAP10,BAP10VS-104,32SWHA001427942,"712177.793109,1530996.977549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บางน้ำเปรี้ยว,C2_P,H23201,H23201,C2_P,H23101,,,,,,,0,,,,,,0,0,1.0513221,,,23-09-2024 20:22:08,09-01-2025 15:40:02
         | 
| 15 | 
            +
            16,5817699872,09-01-2025 15:39:00,1,09-01-2025 15:39:00,09-01-2025 15:39:00,0,0,แผนดับไฟ,BAP,BAP10,BAP10VS-104,32SWHA001427942,"712177.793109,1530996.977549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บางน้ำเปรี้ยว,C2_P,H23201,H23201,C2_P,H23201,,,,,272,314,586,,,,0,0,0,7095,1.0513221,,,23-09-2024 20:22:08,09-01-2025 15:40:02
         | 
| 16 | 
            +
            18,5832279138,09-01-2025 15:23:00,1,09-01-2025 15:24:00,09-01-2025 15:24:00,1,1,แผนดับไฟ,CTA,CTA03,CTA03VB-01,3222CB000000034,"838783.654109,1401980.495549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,จันทบุรี,C2_P,H03101,H03101,C2_P,H03101,,,,,997,,997,,,,997,,997,5900,5.2626816,,,01-10-2024 11:05:34,09-01-2025 15:25:14
         | 
| 17 | 
            +
            19,5832279138,09-01-2025 15:23:00,1,09-01-2025 15:24:00,09-01-2025 15:24:00,1,1,แผนดับไฟ,CTA,CTA03,CTA03VB-01,3222CB000000034,"838783.654109,1401980.495549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,จันทบุรี,C2_P,H03101,H03101,C2_P,H03102,,,,,9226,2,9228,,,,9226,2,9228,44655,5.2626816,,,01-10-2024 11:05:34,09-01-2025 15:25:14
         | 
| 18 | 
            +
            20,5832279138,09-01-2025 15:23:00,1,09-01-2025 15:24:00,09-01-2025 15:24:00,1,1,แผนดับไฟ,CTA,CTA03,CTA03VB-01,3222CB000000034,"838783.654109,1401980.495549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,จันทบุรี,C2_P,H03101,H03101,C2_P,H03302,,,,,41,,41,,,,41,,41,200,5.2626816,,,01-10-2024 11:05:34,09-01-2025 15:25:14
         | 
| 19 | 
            +
            21,5895262759,01-01-2025 10:00:00,1,01-01-2025 10:01:00,01-01-2025 10:01:00,1,1,แผนดับไฟ,-,-,BGP04YS-101,32SHHA000005825,"718222.360109,1484797.077549",Disconnecting Switch_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ชลบุรี,C2_P,H01101,H01101,C2_P,H01101,,,,,0,,0,,,,0,,0,50000,80,,1007871650,06-11-2024 15:09:20,01-01-2025 10:01:36
         | 
| 20 | 
            +
            22,5895262759,01-01-2025 10:00:00,1,01-01-2025 10:01:00,01-01-2025 10:01:00,1,1,แผนดับไฟ,-,-,BGP04YS-101,32SHHA000005825,"718222.360109,1484797.077549",Disconnecting Switch_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ชลบุรี,C2_P,H01101,H01101,C2_P,H20101,นิคมอุตสาหกรรมอมตะซิตี้ ชลบุรี,0,,,,,0,0,,,,,0,50000,80,,1007871650,06-11-2024 15:09:20,01-01-2025 10:01:36
         | 
| 21 | 
            +
            23,5895262759,01-01-2025 10:00:00,1,01-01-2025 10:01:00,01-01-2025 10:01:00,1,1,แผนดับไฟ,-,-,BGP04YS-101,32SHHA000005825,"718222.360109,1484797.077549",Disconnecting Switch_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ชลบุรี,C2_P,H01101,H01101,C2_P,H20101,,,,,,,0,,,,,,0,0,80,,1007871650,06-11-2024 15:09:20,01-01-2025 10:01:36
         | 
| 22 | 
            +
            24,5914246725,09-01-2025 15:26:00,1,09-01-2025 15:26:00,09-01-2025 15:26:00,0,0,แผนดับไฟ,-,-,NKP04YB-01,32CHHA000001746,"731293.435109,1418702.857549",Circuit Breaker_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14101,,,,,,,0,,,,,,0,0,0,,1007830254,15-11-2024 16:04:47,09-01-2025 15:26:52
         | 
| 23 | 
            +
            25,5920756619,09-01-2025 15:27:00,1,09-01-2025 15:27:00,09-01-2025 15:27:00,0,0,แผนดับไฟ,SAT,SAT02,SAT02S-55,32SWHA001449129,"880909.617109,1365093.198549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ตราด,C2_P,H04101,H04101,C2_P,H04101,,,,,,2157,2157,,,,,0,0,8695,0.86330164,,,19-11-2024 14:58:57,09-01-2025 15:28:44
         | 
| 24 | 
            +
            26,5920756619,09-01-2025 15:27:00,1,09-01-2025 15:27:00,09-01-2025 15:27:00,0,0,แผนดับไฟ,SAT,SAT02,SAT02S-55,32SWHA001449129,"880909.617109,1365093.198549",Gas Switch ,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ตราด,C2_P,H04101,H04101,C2_P,H25101,,,,,,0,0,,,,,0,0,160,0.86330164,,,19-11-2024 14:58:57,09-01-2025 15:28:44
         | 
| 25 | 
            +
            28,5929742318,09-01-2025 15:29:00,1,09-01-2025 15:29:00,09-01-2025 15:29:00,0,0,แผนดับไฟ,RAB,RAB01,RAB01VB-01,3221CB000000085,"734370.227109,1410803.309549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14101,,,,2230,,,2230,,,0,,,0,19460,1.1392257,,1007839273,25-11-2024 14:59:59,09-01-2025 15:30:01
         | 
| 26 | 
            +
            29,5935551401,09-01-2025 15:30:00,1,09-01-2025 15:30:00,09-01-2025 15:30:00,0,0,แผนดับไฟ,-,-,KWA01YB-01,32CHHA000002027,"719012.278109,1519156.387549",Circuit Breaker_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บ้านคลองเจ้า,C2_P,H23101,H23101,C2_P,H23101,,,,,,,0,,,,,,0,0,162.956,,1007840785,28-11-2024 17:20:34,09-01-2025 15:31:29
         | 
| 27 | 
            +
            31,5951248351,09-01-2025 15:33:00,1,09-01-2025 15:33:00,09-01-2025 15:33:00,0,0,แผนดับไฟ,TMM,TMM08,TMM08VB-01,3222CB000000006,"826906.158109,1401726.906549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,หนองคล้า,C2_P,H24102,H24102,C2_P,H03201,,,,835,,1,836,,,0,,0,0,3210,4.2251074,,,11-12-2024 17:27:56,09-01-2025 15:34:39
         | 
| 28 | 
            +
            32,5951248351,09-01-2025 15:33:00,1,09-01-2025 15:33:00,09-01-2025 15:33:00,0,0,แผนดับไฟ,TMM,TMM08,TMM08VB-01,3222CB000000006,"826906.158109,1401726.906549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,หนองคล้า,C2_P,H24102,H24102,C2_P,H03202,,,,,42,2939,2981,,,,0,0,0,37165,4.2251074,,,11-12-2024 17:27:56,09-01-2025 15:34:39
         | 
| 29 | 
            +
            33,5951248351,09-01-2025 15:33:00,1,09-01-2025 15:33:00,09-01-2025 15:33:00,0,0,แผนดับไฟ,TMM,TMM08,TMM08VB-01,3222CB000000006,"826906.158109,1401726.906549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,หนองคล้า,C2_P,H24102,H24102,C2_P,H24102,,,,,404,,404,,,,0,,0,1700,4.2251074,,,11-12-2024 17:27:56,09-01-2025 15:34:39
         | 
| 30 | 
            +
            34,5952896804,06-01-2025 16:40:00,1,06-01-2025 16:40:00,06-01-2025 16:40:00,0,0,แผนดับไฟ,-,-,KOA03YS-110,32SHHA000004946,"739930.298109,1512712.182549",Air break Switch_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,อุปกรณ์ป้องกันและตัดตอน,,,ใบมีด,ใบมีด,ไม่มีข้อมูลผู้ผลิต,,,,,,,บางคล้า,C2_P,H05301,H05301,C2_P,H05301,,,,,,,0,,,,,,0,0,0,,1007881171,12-12-2024 14:07:30,06-01-2025 16:41:11
         | 
| 31 | 
            +
            39,5964703769,08-01-2025 17:56:00,1,08-01-2025 17:57:00,08-01-2025 17:57:00,1,1,แผนดับไฟ,CHT,CHT04,CHT04S-03,32SWHA000017321,"710221.494109,1421335.053549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,วังหิน,C2_P,H18101,H18101,C2_P,H18101,,,,,,,0,,,,,,0,0,5.608,,,20-12-2024 10:47:40,08-01-2025 17:59:14
         | 
| 32 | 
            +
            40,5964707527,09-01-2025 12:11:00,1,09-01-2025 12:11:00,09-01-2025 12:11:00,0,0,แผนดับไฟ,CHU,CHU10,CHU08S-04,32SWHA000027021,"706180.175109,1422526.094549",Gas Switch ,Operate,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,เปลี่ยนขนาดสายให้ใหญ่ขึ้น,สายเหนือดิน,สาย,สายหย่อน,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,นาจอมเทียน 4,C2_P,H18101,H18101,C2_P,H18101,,,,,,,0,,,,,,0,0,52.224,,1007863926,20-12-2024 10:51:40,09-01-2025 12:13:10
         | 
| 33 | 
            +
            49,5968645495,17-01-2025 19:46:00,1,17-01-2025 20:46:00,17-01-2025 20:46:00,60,60,แผนดับไฟ,HEA,HEA04,HEA04VB-01,32CBHA000001884,"736936.071109,1445693.759549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,สวิชชิ่งแล้วเสร็จ,ปลวกแดง,C2_P,H16101,H16101,C2_P,H16101,,,,,,2,2,,,,,120,120,110,5.3727114,,1007887861,24-12-2024 09:54:48,17-01-2025 23:11:30
         | 
| 34 | 
            +
            50,5968645495,17-01-2025 19:46:00,1,17-01-2025 20:46:00,17-01-2025 20:46:00,60,60,แผนดับไฟ,HEA,HEA04,HEA04VB-01,32CBHA000001884,"736936.071109,1445693.759549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,สวิชชิ่งแล้วเสร็จ,ปลวกแดง,C2_P,H16101,H16101,C2_P,H19101,นิคมอุตสาหกรรมปิ่นทอง (โครงการ 5),8,,,,,8,480,,,,,480,240,5.3727114,,1007887861,24-12-2024 09:54:48,17-01-2025 23:11:30
         | 
| 35 | 
            +
            51,5968645495,17-01-2025 19:46:00,1,17-01-2025 20:46:00,17-01-2025 20:46:00,60,60,แผนดับไฟ,HEA,HEA04,HEA04VB-01,32CBHA000001884,"736936.071109,1445693.759549",Circuit Breaker_MV,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,สวิชชิ��งแล้วเสร็จ,ปลวกแดง,C2_P,H16101,H16101,C2_P,H19101,,,,,,2284,2284,,,,,137040,137040,95455,5.3727114,,1007887861,24-12-2024 09:54:48,17-01-2025 23:11:30
         | 
| 36 | 
            +
            52,5968647496,05-01-2025 10:29:00,1,05-01-2025 10:30:00,05-01-2025 10:30:00,1,1,แผนดับไฟ,HEB,HEB01,HEB01VS-101,32SWHA001417517,"732966.847109,1452728.823549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,อ.บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,นิคมอุตสาหกรรมดับบลิวเอชเอ อีสเทิร์นซีบอร์ด 2,2,,,,,2,2,,,,,2,60,1.2264385,,1007868496,24-12-2024 09:55:58,05-01-2025 10:36:08
         | 
| 37 | 
            +
            53,5968647496,05-01-2025 10:29:00,1,05-01-2025 10:30:00,05-01-2025 10:30:00,1,1,แผนดับไฟ,HEB,HEB01,HEB01VS-101,32SWHA001417517,"732966.847109,1452728.823549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,อ.บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,3,,,,3,,3,,,,3,7790,1.2264385,,1007868496,24-12-2024 09:55:58,05-01-2025 10:36:08
         | 
| 38 | 
            +
            60,5970024326,05-01-2025 12:13:00,1,05-01-2025 12:13:00,05-01-2025 12:13:00,0,0,แผนดับไฟ,AKA,AKA02,AKA02S-01,32SWHA000004785,"723215.326109,1488212.448549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,บำรุงรักษาตามวาระ,บำรุงรักษาอุปกรณ์,หม้อแปลงสถานี,,,ตัวถัง,ตัวถัง,ไม่มีข้อมูลผู้ผลิต,,,,,,,อมตะ1,C2_P,H20101,H20101,C2_P,H20101,,,,,,0,0,,,,,0,0,100,29.856,,1007880098,25-12-2024 14:47:17,05-01-2025 12:15:44
         | 
| 39 | 
            +
            75,5970798027,12-01-2025 18:23:00,1,12-01-2025 18:28:00,12-01-2025 18:28:00,5,5,แผนดับไฟ,PYO,PYO08,PYO08S-01,32SWHA001419684,"712444.831109,1435737.279549",Disconnecting Switch,Operate,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ก่อสร้างระบบใหม่,ระบบจำหน่าย,สายเหนือดิน,เสา,,เสาคอนกรีต,เปลือย,ไม่มีข้อมูลผู้ผลิต,,,,,,"สวิชชิ่งแล้วเสร็จ
         | 
| 40 | 
            +
            งานปักเสา 22ม. และตัดสายข้ามทาง PYO8",เมืองพัทยา,C2_P,H06101,H06101,C2_P,H06101,,,,,,,0,,,,,,0,0,0,,1007887862,26-12-2024 13:17:40,13-01-2025 06:44:44
         | 
| 41 | 
            +
            76,5970879405,01-01-2025 16:42:00,1,01-01-2025 16:42:00,01-01-2025 16:42:00,0,0,แผนดับไฟ,-,-,KWA02YS-710,32SHHA000005329,"711006.192109,1525280.839549",Air break Switch_HV,Operate,ABC,115 kV,22 kV,22 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,ปรับปรุงระบบ,ปรับปรุงอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,สวิชชิ่งแล้วเสร็จ,บ้านคลองเจ้า,C2_P,H23101,H23101,C2_P,H23101,,,,,,0,0,,,,,0,0,200000,160,,1007875864,26-12-2024 15:19:13,01-01-2025 17:07:28
         | 
| 42 | 
            +
            89,5971444594,02-01-2025 15:48:00,1,02-01-2025 15:53:00,02-01-2025 15:53:00,5,5,แผนดับไฟ,-,-,BWN01YS-701,32SHHA000005496,"729162.835109,1445948.939549",Air break Switch_HV,Operate,ABC,115 kV,115 kV,115 kV,ระบบสายส่ง,กฟภ.-แผนดับไฟ,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,บำรุงรักษาตามวาระ,บำรุงรักษาอุปกรณ์,สายเหนือดิน,สาย,,เปลือย,เปลือย,ไม่มีข้อมูลผู้ผลิต,,,,,,"สวิชชิ่งดำเนินการแล้วเสร็จ 
         | 
| 43 | 
            +
            งาน PM บริษัทแคนนาเดียนโซล่า",บึง,C2_P,H19101,H19101,C2_P,H19101,,,,,,0,0,,,,,0,0,100000,80,,1007875865,27-12-2024 10:43:27,02-01-2025 16:19:33
         | 
| 44 | 
            +
            145,5974117216,01-01-2025 02:29:09,1,01-01-2025 02:29:10,01-01-2025 02:29:10,0.02,0.02,ไฟฟ้าขัดข้อง,APA,APA03,APA03VB-01,3220CB000000154,"708989.127109,1451738.941549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,สายขาด,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 45 | 
            +
            สาเหตุ สายขาดกลางสแปนไม่ตกพื้น ",แหลมฉบัง,C2_P,H22101,H22101,C2_P,H22101,,,3192,,,,3192,,33.25,,,,33.25,4840,6.641457,,,01-01-2025 02:29:13,01-01-2025 07:35:00
         | 
| 46 | 
            +
            146,5974119115,01-01-2025 02:29:09,1,01-01-2025 02:29:10,01-01-2025 02:29:10,0.02,0.02,ไฟฟ้าขัดข้อง,APA,APA02,APA02VB-01,3220CB000000155,"708989.127109,1451738.941549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,สายขาด,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 47 | 
            +
            สาเหตุ สายขาดกลางสแปนไม่ตกพื้น ชนิดสาย SAC",แหลมฉบัง,C2_P,H22101,H22101,C2_P,H22101,,,3853,,,,3853,,40.90601667,,,,40.90601667,42465,3.454099,,,01-01-2025 02:30:36,01-01-2025 07:42:34
         | 
| 48 | 
            +
            192,5974256039,01-01-2025 06:23:35,1,01-01-2025 06:23:40,01-01-2025 06:23:40,0.08,0.08,ไฟฟ้าขัดข้อง,NYM,NYM09,KAA02R-02,32RCHA000027039,"797476.511109,1416968.515549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แกลง,C2_P,H09101,H09101,C2_P,H09101,,,,,,2010,2010,,,,,168.706,168.706,9060,0.7781869,,,01-01-2025 06:23:39,01-01-2025 07:10:11
         | 
| 49 | 
            +
            206,5974258830,01-01-2025 06:46:08,1,01-01-2025 06:46:13,01-01-2025 06:46:13,0.08,0.08,ไฟฟ้าขัดข้อง,PTP,PTP04,PTP03R-01,3220RC000000007,"726761.604109,1490769.622549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พานทอง,C2_P,H20101,H20101,C2_P,H10101,,,,,6,,6,,,,0.5028,,0.5028,30,0.9898573,,,01-01-2025 06:46:10,01-01-2025 07:09:28
         | 
    	
        data/data_2.csv
    ADDED
    
    | @@ -0,0 +1,66 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            Number,EventNumber,OutageDateTime,CountOfRestoStep,FirstRestoDateTime,LastRestoDateTime,FirstStepDuration,LastStepDuration,EventType,SubstationID,Feeder,OpDeviceID,OpDeviceGIStag,OpDeviceXYcoord,OpDeviceType,OpDeviceStatus,OpDevicePhase,OpVolt,OpVolt1,OpVolt2,OpDeviceSysType,Owner,FaultSysType,KnowUnknowCause,Weather,CauseType,SubCauseType,FaultDeviceType,FaultDevice,FaultDeviceCondition,Parts,DamagedParts,Manufacturer,RelayType,Relation,RelayPhase,RelayStatus,Detail,FaultDetail,SiteDetail,OpDeviceAreaID,OpDeviceSiteID,EventSiteID,AffectedAreaID,AffectedSiteID,Industrial,AffectedCustomer1,AffectedCustomer2,AffectedCustomer3,AffectedCustomer4,AffectedCustomer5,AffectedCustomer,AllStepCusXTime1,AllStepCusXTime2,AllStepCusXTime3,AllStepCusXTime4,AllStepCusXTime5,AllStepCusXTime,Capacity(kVA),Load(MW),CorrectionDetail,WorkOrderID,CreateEventDateTime,CloseEventDateTime
         | 
| 2 | 
            +
            192,5974256039,01-01-2025 06:23:35,1,01-01-2025 06:23:40,01-01-2025 06:23:40,0.08,0.08,ไฟฟ้าขัดข้อง,NYM,NYM09,KAA02R-02,32RCHA000027039,"797476.511109,1416968.515549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แกลง,C2_P,H09101,H09101,C2_P,H09101,,,,,,2010,2010,,,,,168.706,168.706,9060,0.7781869,,,01-01-2025 06:23:39,01-01-2025 07:10:11
         | 
| 3 | 
            +
            206,5974258830,01-01-2025 06:46:08,1,01-01-2025 06:46:13,01-01-2025 06:46:13,0.08,0.08,ไฟฟ้าขัดข้อง,PTP,PTP04,PTP03R-01,3220RC000000007,"726761.604109,1490769.622549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พานทอง,C2_P,H20101,H20101,C2_P,H10101,,,,,6,,6,,,,0.5028,,0.5028,30,0.9898573,,,01-01-2025 06:46:10,01-01-2025 07:09:28
         | 
| 4 | 
            +
            207,5974258830,01-01-2025 06:46:08,1,01-01-2025 06:46:13,01-01-2025 06:46:13,0.08,0.08,ไฟฟ้าขัดข้อง,PTP,PTP04,PTP03R-01,3220RC000000007,"726761.604109,1490769.622549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พานทอง,C2_P,H20101,H20101,C2_P,H20101,,,,,99,1893,1992,,,,8.2962,158.6334,166.9296,9960,0.9898573,,,01-01-2025 06:46:10,01-01-2025 07:09:28
         | 
| 5 | 
            +
            393,5974416873,01-01-2025 09:11:19,1,01-01-2025 09:11:45,01-01-2025 09:11:45,0.43,0.43,ไฟฟ้าขัดข้อง,PNU,PNU02,PNUBR-02,32CBHA000006370,"872522.831109,1444925.700549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,สอยดาว,C2_P,H21101,H21101,C2_P,H21101,,,,,,557,557,,,,,234.3763167,234.3763167,5420,2.8225032,,,01-01-2025 09:11:25,01-01-2025 09:28:55
         | 
| 6 | 
            +
            461,5974432123,01-01-2025 10:15:05,1,01-01-2025 10:15:10,01-01-2025 10:15:10,0.08,0.08,ไฟฟ้าขัดข้อง,TTA,TTA10,TTA10R-01,32RCHA000002222,"893355.312109,1356741.770549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ตราด,C2_P,H04101,H04101,C2_P,H04101,,,,,808,1606,2414,,,,70.2152,139.5614,209.7766,16125,1.23922,,,01-01-2025 10:15:07,01-01-2025 10:46:24
         | 
| 7 | 
            +
            462,5974432123,01-01-2025 10:15:05,1,01-01-2025 10:15:10,01-01-2025 10:15:10,0.08,0.08,ไฟฟ้าขัดข้อง,TTA,TTA10,TTA10R-01,32RCHA000002222,"893355.312109,1356741.770549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ตราด,C2_P,H04101,H04101,C2_P,H04501,,,,,,,0,,,,,,0,0,1.23922,,,01-01-2025 10:15:07,01-01-2025 10:46:24
         | 
| 8 | 
            +
            470,5974433886,01-01-2025 10:20:41,1,01-01-2025 10:20:46,01-01-2025 10:20:46,0.08,0.08,ไฟฟ้าขัดข้อง,NOY,NOY01,NOY01R-01,32RCHA000027924,"747838.843109,1448733.160549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,หนองใหญ่,C2_P,H12201,H12201,C2_P,H12201,,,,,,415,415,,,,,34.7355,34.7355,8150,1.0486464,,,01-01-2025 10:20:44,01-01-2025 10:45:54
         | 
| 9 | 
            +
            484,5974453978,01-01-2025 10:43:17,1,01-01-2025 10:43:18,01-01-2025 10:43:18,0.02,0.02,ไฟฟ้าขัดข้อง,CCB,CCB09,CCB09VB-01,32CBHA000013162,"725837.027109,1511125.476549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์,ชำรุด,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,ฉะเชิงเทรา,C2_P,H05101,H05101,C2_P,H05101,,,,,,318,318,,,,,2.6447,2.6447,3160,0.28109396,,,01-01-2025 10:43:20,01-01-2025 12:40:25
         | 
| 10 | 
            +
            523,5974466027,01-01-2025 11:30:31,1,01-01-2025 11:30:31,01-01-2025 11:30:31,0,0,ไฟฟ้าขัดข้อง,MPC,MPC03,MPC03VB-01,3221CB000000074,"736229.792109,1406024.463549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H02101,,,,,,,0,,,,,,0,0,1.8875446,,,01-01-2025 11:30:46,01-01-2025 13:16:55
         | 
| 11 | 
            +
            524,5974466027,01-01-2025 11:30:31,1,01-01-2025 11:30:31,01-01-2025 11:30:31,0,0,ไฟฟ้าขัดข้อง,MPC,MPC03,MPC03VB-01,3221CB000000074,"736229.792109,1406024.463549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14101,,,,755,193,,948,,,7.411583333,1.894616667,,9.3062,16185,1.8875446,,,01-01-2025 11:30:46,01-01-2025 13:16:55
         | 
| 12 | 
            +
            537,5974470761,01-01-2025 11:53:00,1,01-01-2025 12:00:00,01-01-2025 12:00:00,7,7,ไฟฟ้าขัดข้อง,KLG,KLG09,KLG04F-43,3222SW000000454,"835694.899109,1381249.763549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สัตว์,นก/ค้างคาว,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,-,C2_P,H03601,H03601,C2_P,H03601,,,,,193,,193,,,,1351,,1351,3240,0.08130017,,1007876066,01-01-2025 11:54:01,01-01-2025 12:02:50
         | 
| 13 | 
            +
            564,5974482942,01-01-2025 12:36:11,2,01-01-2025 12:36:11,01-01-2025 12:36:16,0,0.08,ไฟฟ้าขัดข้อง,CTA,CTA03,CTA03R-02,3222RC000000018,"840991.925109,1399345.838549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,มะขาม,C2_P,H03102,H03102,C2_P,H03102,,,,,1909,,1909,,,,159.7196667,,159.7196667,7420,0.564784,,,01-01-2025 12:36:13,01-01-2025 12:38:53
         | 
| 14 | 
            +
            643,5974514196,01-01-2025 14:14:00,1,01-01-2025 14:31:00,01-01-2025 14:31:00,17,17,ไฟฟ้าขัดข้อง,BBA,BBA06,BBA06F-04,3220SW000000678,"734503.149109,1470695.873549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สัตว์,กระรอก/กระแต/หนู,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,อ.บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,,,1,,1,,,,17,,17,250,0.001662634,,1007876171,01-01-2025 14:14:18,01-01-2025 14:31:50
         | 
| 15 | 
            +
            712,5974563148,01-01-2025 15:11:40,1,01-01-2025 15:11:41,01-01-2025 15:11:41,0.02,0.02,ไฟฟ้าขัดข้อง,CCX,CCX03,CCX03BR-01,32CBHA000003019,"721765.570109,1515969.177549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ฉะเชิงเทรา,C2_P,H05101,H05101,C2_P,H05101,,,,1578,,2,1580,,,13.5182,,0.017133333,13.53533333,17125,1.6410364,,,01-01-2025 15:13:49,01-01-2025 15:58:12
         | 
| 16 | 
            +
            728,5974566179,01-01-2025 15:26:39,1,01-01-2025 15:26:44,01-01-2025 15:26:44,0.08,0.08,ไฟฟ้าขัดข้อง,SNK,SNK03,SNK03R-03,32RCHA000003627,"784515.266109,1486209.416549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ท่าตะเกียบ,C2_P,H15202,H15202,C2_P,H15202,,,,,,1194,1194,,,,,98.1269,98.1269,2270,0.3736475,,,01-01-2025 15:26:42,01-01-2025 15:28:14
         | 
| 17 | 
            +
            756,5974581339,01-01-2025 15:51:00,1,01-01-2025 16:21:00,01-01-2025 16:21:00,30,30,ไฟฟ้าขัดข้อง,NYM,NYM08,51-013694,3222XF000004466,"809087.826109,1432590.327549",Single Phase Transformer,Operate,AC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,โหลดเกินพิกัด,โหลดเกินพิกัด,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงต่ำ,,,,,,,,,-,C2_P,H24103,H24103,C2_P,H24103,,,,,,7,7,,,,,210,210,30,0.00319067,,1007876256,01-01-2025 15:51:30,01-01-2025 15:54:15
         | 
| 18 | 
            +
            840,5974604293,01-01-2025 16:55:59,1,01-01-2025 16:56:04,01-01-2025 16:56:04,0.08,0.08,ไฟฟ้าขัดข้อง,KAC,KAC10,KAC05R-01,32RCHA000002926,"778523.293109,1407183.638549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แกลง,C2_P,H09101,H09101,C2_P,H09101,,,,,836,15,851,,,,70.1822,1.25925,71.44145,4435,0.4343222,,,01-01-2025 16:56:03,01-01-2025 18:15:57
         | 
| 19 | 
            +
            940,5974631064,01-01-2025 18:18:36,1,01-01-2025 18:18:36,01-01-2025 18:18:36,0,0,ไฟฟ้าขัดข้อง,TMM,TMM08,TMM08R-01,32RCHA000005725,"817415.330109,1394032.679549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,เตาหม้อ,C2_P,H03202,H03202,C2_P,H03201,,,,,,1,1,,,,,0.001716667,0.001716667,30,2.6711262,,,01-01-2025 18:18:37,01-01-2025 18:32:06
         | 
| 20 | 
            +
            941,5974631064,01-01-2025 18:18:36,1,01-01-2025 18:18:36,01-01-2025 18:18:36,0,0,ไฟฟ้าขัดข้อง,TMM,TMM08,TMM08R-01,32RCHA000005725,"817415.330109,1394032.679549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟ��.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,เตาหม้อ,C2_P,H03202,H03202,C2_P,H03202,,,,,45,1864,1909,,,,0.07725,3.199866667,3.277116667,30135,2.6711262,,,01-01-2025 18:18:37,01-01-2025 18:32:06
         | 
| 21 | 
            +
            1081,5974662124,01-01-2025 20:04:00,1,01-01-2025 20:04:01,01-01-2025 20:04:01,0.02,0.02,ไฟฟ้าขัดข้อง,APA,APA07,APA07VB-01,3220CB000000172,"708989.127109,1451738.941549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แหลมฉบัง,C2_P,H22101,H22101,C2_P,H22101,,,2984,,,,2984,,33.91813333,,,,33.91813333,26985,3.017963,,,01-01-2025 20:04:02,01-01-2025 21:33:23
         | 
| 22 | 
            +
            1432,5974842919,02-01-2025 08:01:58,2,02-01-2025 08:01:58,02-01-2025 08:02:03,0,0.08,ไฟฟ้าขัดข้อง,KLG,KLG06,KLG06VR-104,32RCHA000027778,"861471.977109,1403997.586549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บ่อเวฬ,C2_P,H03302,H03302,C2_P,H03302,,,,,734,,734,,,,60.1146,,60.1146,8475,0.42855933,,,02-01-2025 08:02:01,02-01-2025 08:10:10
         | 
| 23 | 
            +
            1433,5974842919,02-01-2025 08:01:58,2,02-01-2025 08:01:58,02-01-2025 08:02:03,0,0.08,ไฟฟ้าขัดข้อง,KLG,KLG06,KLG06VR-104,32RCHA000027778,"861471.977109,1403997.586549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,บ่อเวฬ,C2_P,H03302,H03302,C2_P,H25102,,,,,0,,0,,,,0,,0,480,0.42855933,,,02-01-2025 08:02:01,02-01-2025 08:10:10
         | 
| 24 | 
            +
            1445,5974848669,02-01-2025 08:16:00,1,02-01-2025 09:09:00,02-01-2025 09:09:00,53,53,ไฟฟ้าขัดข้อง,SCB,SCB06,6600242122,3220PT000000427,"715482.146109,1455246.524549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์,ชำรุด,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงต่ำ,,,,,,,,,บจก.เอสซีจี แลนด์สเคป,C2_P,H07101,H07101,C2_P,H07101,,,1,,,,1,,52.99515,,,,52.99515,30,0.026199276,,1007877867,02-01-2025 08:16:00,03-01-2025 08:09:56
         | 
| 25 | 
            +
            1763,5975012988,02-01-2025 12:06:22,1,02-01-2025 12:06:27,02-01-2025 12:06:27,0.08,0.08,ไฟฟ้าขัดข้อง,NOY,NOY09,NOY09VR-101,32RCHA000004147,"744156.859109,1459766.486549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,,,,1099,1099,,,,,91.96798333,91.96798333,15155,2.6658318,,,02-01-2025 12:06:27,02-01-2025 12:54:58
         | 
| 26 | 
            +
            1764,5975012988,02-01-2025 12:06:22,1,02-01-2025 12:06:27,02-01-2025 12:06:27,0.08,0.08,ไฟฟ้าขัดข้อง,NOY,NOY09,NOY09VR-101,32RCHA000004147,"744156.859109,1459766.486549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือด��น,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บ้านบึง,C2_P,H12101,H12101,C2_P,H12201,,,,,,,0,,,,,,0,0,2.6658318,,,02-01-2025 12:06:27,02-01-2025 12:54:58
         | 
| 27 | 
            +
            1899,5975070346,02-01-2025 13:48:36,1,02-01-2025 13:48:41,02-01-2025 13:48:41,0.08,0.08,ไฟฟ้าขัดข้อง,RAD,RAD07,RAA03R-02,32RCHA000001604,"743310.853109,1405874.593549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,ระยอง,C2_P,H02101,H02101,C2_P,H02101,,,,,2954,,2954,,,,256.6533667,,256.6533667,10095,1.49817,,,02-01-2025 13:48:39,02-01-2025 13:50:01
         | 
| 28 | 
            +
            2151,5975257775,02-01-2025 18:07:14,1,02-01-2025 18:07:19,02-01-2025 18:07:19,0.08,0.08,ไฟฟ้าขัดข้อง,SNK,SNK10,SNK10R-02,32RCHA000003926,"778331.816109,1497005.806549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,กับดักฟ้าผ่า,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,ท่าตะเกียบ,C2_P,H15202,H15202,C2_P,H15202,,,,,,1439,1439,,,,,118.2378333,118.2378333,2080,0.36891946,,,02-01-2025 18:07:18,02-01-2025 20:01:27
         | 
| 29 | 
            +
            2303,5975355304,02-01-2025 19:34:27,1,02-01-2025 21:41:00,02-01-2025 21:41:00,126.55,126.55,ไฟฟ้าขัดข้อง,BBB,BBB07,6400050068-1060070717,6400050068-1060070717,"731513.403108,1464267.387549",Meter,Operate,,Unknown,22 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สัตว์,กระรอก/กระแต/หนู,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงสูง,,,,,,,,,อ.บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,,,,1,1,,,,,126.5381667,126.5381667,,0.17238707,,1007877659,02-01-2025 21:24:51,02-01-2025 21:41:59
         | 
| 30 | 
            +
            2420,5975401420,03-01-2025 01:34:39,1,03-01-2025 01:34:44,03-01-2025 01:34:44,0.08,0.08,ไฟฟ้าขัดข้อง,NOY,NOY01,NOY01R-01,32RCHA000027924,"747838.843109,1448733.160549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,หนองใหญ่,C2_P,H12201,H12201,C2_P,H12201,,,,,,415,415,,,,,34.79775,34.79775,8150,1.0032551,,,03-01-2025 01:34:42,03-01-2025 03:52:11
         | 
| 31 | 
            +
            2469,5975448365,03-01-2025 06:52:49,2,03-01-2025 06:52:53,03-01-2025 06:52:59,0.07,0.17,ไฟฟ้าขัดข้อง,KMK,KMK10,KMK01R-01,32RCHA000004748,"716856.496109,1438970.082549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,เมืองพัทยา,C2_P,H06101,H06101,C2_P,H06101,,,,,310,,310,,,,36.58516667,,36.58516667,7430,0.5538954,,,03-01-2025 06:52:51,03-01-2025 06:54:28
         | 
| 32 | 
            +
            3041,5975764994,03-01-2025 12:02:37,2,03-01-2025 12:02:37,03-01-2025 12:02:42,0,0.08,ไฟฟ้าขัดข้อง,KAA,KAA10,KAA10R-01,32RCHA000027058,"784611.381109,1424883.346549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุก���รณ์ทริปรีโคลส,แกลง,C2_P,H09101,H09101,C2_P,H09101,,,,,,751,751,,,,,61.21901667,61.21901667,2190,0.25038603,,,03-01-2025 12:02:40,03-01-2025 12:18:40
         | 
| 33 | 
            +
            3137,5975797213,03-01-2025 13:16:00,1,03-01-2025 13:17:00,03-01-2025 13:17:00,1,1,ไฟฟ้าขัดข้อง,BBA,BBA02,BBA02VB-01,3220CB000000114,"740887.461109,1462461.911549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,,,,,0,,,,,,0,0,0,,,03-01-2025 13:18:39,03-01-2025 15:12:58
         | 
| 34 | 
            +
            3180,5975829233,03-01-2025 13:56:09,1,03-01-2025 13:56:14,03-01-2025 13:56:14,0.08,0.08,ไฟฟ้าขัดข้อง,NOY,NOY09,NOY09VR-101,32RCHA000004147,"744156.859109,1459766.486549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,,,,1097,1097,,,,,91.98345,91.98345,15155,2.6368174,,,03-01-2025 13:56:11,03-01-2025 14:18:44
         | 
| 35 | 
            +
            3181,5975829233,03-01-2025 13:56:09,1,03-01-2025 13:56:14,03-01-2025 13:56:14,0.08,0.08,ไฟฟ้าขัดข้อง,NOY,NOY09,NOY09VR-101,32RCHA000004147,"744156.859109,1459766.486549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บ้านบึง,C2_P,H12101,H12101,C2_P,H12201,,,,,,,0,,,,,,0,0,2.6368174,,,03-01-2025 13:56:11,03-01-2025 14:18:44
         | 
| 36 | 
            +
            3220,5975856984,03-01-2025 14:33:31,1,03-01-2025 14:33:31,03-01-2025 14:33:31,0,0,ไฟฟ้าขัดข้อง,RAA,RAA05,RAA05VB-01,3221CB000000023,"746674.723109,1403906.443549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,ระยอง,C2_P,H02101,H02101,C2_P,H02101,,,2011,,1778,427,4216,,22.25506667,,19.67653333,4.725466667,46.65706667,23150,2.9845632,,,03-01-2025 14:33:35,03-01-2025 15:14:45
         | 
| 37 | 
            +
            3259,5975881669,03-01-2025 14:50:42,1,03-01-2025 14:50:43,03-01-2025 14:50:43,0.02,0.02,ไฟฟ้าขัดข้อง,CCB,CCB09,CCB09VB-01,32CBHA000013162,"725837.027109,1511125.476549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,ฉะเชิงเทรา,C2_P,H05101,H05101,C2_P,H05101,,,,,,318,318,,,,,2.6447,2.6447,3160,0.27845935,,,03-01-2025 14:50:45,03-01-2025 15:14:15
         | 
| 38 | 
            +
            3263,5975882573,03-01-2025 14:51:38,1,03-01-2025 14:51:43,03-01-2025 14:51:43,0.08,0.08,ไฟฟ้าขัดข้อง,BAK,BAK05,BAK05R-01,32RCHA000004386,"738111.787109,1525104.054549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บางคล้า,C2_P,H05301,H05301,C2_P,H05301,,,,,,1330,1330,,,,,109.5033333,109.5033333,9615,1.1235221,,,03-01-2025 14:51:42,03-01-2025 14:58:31
         | 
| 39 | 
            +
            3264,5975882573,03-01-2025 14:51:38,1,03-01-2025 14:51:43,03-01-2025 14:51:43,0.08,0.08,ไฟฟ้าขัดข้อง,BAK,BAK05,BAK05R-01,32RCHA000004386,"738111.787109,1525104.054549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,บางคล้า,C2_P,H05301,H05301,C2_P,H05303,,,,,,59,59,,,,,4.857666667,4.857666667,50,1.1235221,,,03-01-2025 14:51:42,03-01-2025 14:58:31
         | 
| 40 | 
            +
            3401,5975946566,03-01-2025 16:09:29,1,03-01-2025 16:09:34,03-01-2025 16:09:34,0.08,0.08,ไฟฟ้าขัดข้อง,BYA,BYA03,RAA01R-02,3221RC000000022,"756111.353109,1399088.432549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,ระยอง,C2_P,H02101,H02101,C2_P,H02101,,,,,,4930,4930,,,,,395.1395,395.1395,17675,2.3163035,,,03-01-2025 16:09:31,03-01-2025 16:15:19
         | 
| 41 | 
            +
            3508,5975992650,03-01-2025 17:20:14,1,03-01-2025 17:20:19,03-01-2025 17:20:19,0.08,0.08,ไฟฟ้าขัดข้อง,PTP,PTP04,PTP03R-01,3220RC000000007,"726761.604109,1490769.622549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พานทอง,C2_P,H20101,H20101,C2_P,H10101,,,,,6,,6,,,,0.5028,,0.5028,30,0.98500793,,,03-01-2025 17:20:16,03-01-2025 18:30:37
         | 
| 42 | 
            +
            3509,5975992650,03-01-2025 17:20:14,1,03-01-2025 17:20:19,03-01-2025 17:20:19,0.08,0.08,ไฟฟ้าขัดข้อง,PTP,PTP04,PTP03R-01,3220RC000000007,"726761.604109,1490769.622549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พานทอง,C2_P,H20101,H20101,C2_P,H20101,,,,,99,1892,1991,,,,8.2962,158.5496,166.8458,9960,0.98500793,,,03-01-2025 17:20:16,03-01-2025 18:30:37
         | 
| 43 | 
            +
            3536,5976008507,03-01-2025 17:46:05,1,03-01-2025 17:46:10,03-01-2025 17:46:10,0.08,0.08,ไฟฟ้าขัดข้อง,KAA,KAA04,KAA04R-03,3221RC000000024,"790134.024109,1420829.389549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แกลง,C2_P,H09101,H09101,C2_P,H09101,,,,,1027,599,1626,,,,85.73738333,50.00651667,135.7439,3330,0.59016595,,,03-01-2025 17:46:08,03-01-2025 18:29:59
         | 
| 44 | 
            +
            3561,5976018114,03-01-2025 18:01:00,1,03-01-2025 18:21:00,03-01-2025 18:21:00,20,20,ไฟฟ้าขัดข้อง,BBB,BBB06,BBB06F-03-003,32SWHA001433036,"727053.354109,1469085.277549",Drop out Fuse,D/F,AB,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สภาพสิ่งแวดล้อม,การผุกร่อน/สนิม,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,อ.บ้านบึง,C2_P,H12101,H12101,C2_P,H12101,,,,,6,,6,,,,120,,120,110,0.002664855,,1007878742,03-01-2025 18:01:33,03-01-2025 18:22:58
         | 
| 45 | 
            +
            3612,5976038309,03-01-2025 18:47:00,1,03-01-2025 19:32:00,03-01-2025 19:32:00,45,45,ไฟฟ้าขัดข้อง,NOU,NOU03,NOY01F-08-002,32SWHA001410130,"754353.446109,1449630.388549",Drop out Fuse,D/F,AC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สภาพสิ่งแวดล้อม,การผุกร่อน/สนิม,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,อ.หนองใหญ่,C2_P,H12201,H12201,C2_P,H12201,,,,,42,15,57,,,,1890,675,2565,150,0.026781088,,1007878801,03-01-2025 18:47:18,03-01-2025 19:33:45
         | 
| 46 | 
            +
            3876,5976174264,04-01-2025 04:11:53,1,04-01-2025 04:11:59,04-01-2025 04:11:59,0.1,0.1,ไฟฟ้าขัดข้อง,PNU,PNU02,PNU02R-01,32RCHA000004940,"873714.691109,1449192.573549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,สอยดาว,C2_P,H21101,H21101,C2_P,H21101,,,,,,1,1,,,,,0.087083333,0.087083333,30,2.07,,,04-01-2025 04:11:58,04-01-2025 04:24:00
         | 
| 47 | 
            +
            3950,5976211060,04-01-2025 07:09:06,1,04-01-2025 07:09:11,04-01-2025 07:09:11,0.08,0.08,ไฟฟ้าขัดข้อง,PHA,PHA05,PHA05R-01,3224RC000000021,"760280.225109,1526999.042549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พนมสารคาม,C2_P,H15101,H15101,C2_P,H15101,,,,,278,705,983,,,,22.39753333,56.7995,79.19703333,12230,2.9399443,,,04-01-2025 07:09:09,04-01-2025 07:32:53
         | 
| 48 | 
            +
            3972,5976222849,04-01-2025 07:20:07,1,04-01-2025 07:20:12,04-01-2025 07:20:12,0.08,0.08,ไฟฟ้าขัดข้อง,GUU,GUU02,GUU02R-01,3222RC000000036,"816886.026109,1444244.276549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แก่งหางแมว,C2_P,H24103,H24103,C2_P,H24103,,,,,24,2611,2635,,,,2.0064,218.2796,220.286,6310,0.69164606,,,04-01-2025 07:20:09,04-01-2025 07:41:46
         | 
| 49 | 
            +
            4051,5976245076,04-01-2025 06:36:00,1,04-01-2025 06:37:00,04-01-2025 06:37:00,1,1,ไฟฟ้าขัดข้อง,KWC,KWC04,KWC04VB-01,32CBHA000014003,"712620.903109,1523378.109549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 50 | 
            +
            ",บ้านคลองเจ้า,C2_P,H23101,H23101,C2_P,H23101,,,,,,97,97,,,,,97,97,29420,3.6803796,,,04-01-2025 08:09:38,04-01-2025 13:00:02
         | 
| 51 | 
            +
            4111,5976277103,04-01-2025 09:18:05,1,04-01-2025 09:18:10,04-01-2025 09:18:10,0.08,0.08,ไฟฟ้าขัดข้อง,KLG,KLG03,KLG03VR-102,32RCHA000028217,"836526.979109,1379720.800549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,แหลมสิงห์,C2_P,H03601,H03601,C2_P,H03601,,,,,166,17,183,,,,13.94676667,1.428283333,15.37505,5610,0.5237769,,,04-01-2025 09:18:08,04-01-2025 09:36:04
         | 
| 52 | 
            +
            4147,5976290999,04-01-2025 09:50:19,1,04-01-2025 09:50:24,04-01-2025 09:50:24,0.08,0.08,ไฟฟ้าขัดข้อง,GUU,GUU01,GUU01R-01,32RCHA000027900,"823663.604109,1421968.577549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,หนองคล้า,C2_P,H24102,H24102,C2_P,H24102,,,,,,13,13,,,,,1.089833333,1.089833333,100,0.008436355,,,04-01-2025 09:50:23,04-01-2025 09:54:29
         | 
| 53 | 
            +
            4332,5976353885,04-01-2025 11:24:17,2,04-01-2025 11:24:18,04-01-2025 11:24:33,0.02,0.27,ไฟฟ้าขัดข้อง,NYM,NYM05,NYM05VB-01,3222CB000000014,"808721.423109,1413607.679549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,กับดักฟ้าผ่า,,ล่อฟ้า,ล่อฟ้า,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 54 | 
            +
            สาเหตุ ล่อฟ้าชำรุดเฟส B บ.นัทาศิลา ห่าง NYM5S-03 ประมาณ 4 กม.",นายายอาม,C2_P,H24101,H24101,C2_P,H09101,,,,,2003,983,2986,,,,523.48405,256.90705,780.3911,37995,2.525252,,,04-01-2025 11:25:29,04-01-2025 15:17:40
         | 
| 55 | 
            +
            4333,5976353885,04-01-2025 11:24:17,2,04-01-2025 11:24:18,04-01-2025 11:24:33,0.02,0.27,ไฟฟ้าขัดข้อง,NYM,NYM05,NYM05VB-01,3222CB000000014,"808721.423109,1413607.679549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,กับดักฟ้าผ่า,,ล่อฟ้า,ล่อฟ้า,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 56 | 
            +
            สาเหตุ ล่อฟ้าชำรุดเฟส B บ.นัทาศิลา ห่าง NYM5S-03 ประมาณ 4 กม.",นายายอาม,C2_P,H24101,H24101,C2_P,H24101,,,,,459,1,460,,,,119.95965,0.26135,120.221,2755,2.525252,,,04-01-2025 11:25:29,04-01-2025 15:17:40
         | 
| 57 | 
            +
            4513,5976463340,04-01-2025 13:56:00,1,04-01-2025 13:57:00,04-01-2025 13:57:00,1,1,ไฟฟ้าขัดข้อง,KLG,KLG01,KLG01VB-01,3222CB000000022,"852821.169109,1382468.131549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,สายขาด,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 58 | 
            +
            สาเหตุ สายหลีดขาดเฟส B",ขลุง,C2_P,H03301,H03301,C2_P,H03301,,,,,1814,3626,5440,,,,1814,3626,5440,20125,2.0848394,,,04-01-2025 14:02:30,04-01-2025 14:56:56
         | 
| 59 | 
            +
            4514,5976463340,04-01-2025 13:56:00,1,04-01-2025 13:57:00,04-01-2025 13:57:00,1,1,ไฟฟ้าขัดข้อง,KLG,KLG01,KLG01VB-01,3222CB000000022,"852821.169109,1382468.131549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,สายขาด,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,"เป็นเหตุการณ์ทริปรีโคลส
         | 
| 60 | 
            +
            สาเหตุ สายหลีดขาดเฟส B",ขลุง,C2_P,H03301,H03301,C2_P,H03302,,,,,1,132,133,,,,1,132,133,540,2.0848394,,,04-01-2025 14:02:30,04-01-2025 14:56:56
         | 
| 61 | 
            +
            4654,5976533287,04-01-2025 16:04:00,1,04-01-2025 16:04:04,04-01-2025 16:04:04,0.07,0.07,ไฟฟ้าขัดข้อง,KAC,KAC08,KAC08R-01,32RCHA000000948,"786312.085109,1401971.398549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้า���ัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,กร่ำ,C2_P,H09103,H09103,C2_P,H09103,,,,,1376,,1376,,,,111.0432,,111.0432,20585,1.3379481,,,04-01-2025 16:04:02,04-01-2025 18:15:48
         | 
| 62 | 
            +
            4668,5976537566,04-01-2025 16:03:00,1,04-01-2025 16:04:00,04-01-2025 16:04:00,1,1,ไฟฟ้าขัดข้อง,LMA,LMA02,LMA02VB-01,32CBHA000014100,"767787.574109,1408554.703549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,เพ,C2_P,H02201,H02201,C2_P,H02201,,,,,,,0,,,,,,0,0,0,,,04-01-2025 16:09:28,05-01-2025 07:23:53
         | 
| 63 | 
            +
            4692,5976543217,04-01-2025 16:25:11,1,04-01-2025 16:25:11,04-01-2025 16:25:11,0,0,ไฟฟ้าขัดข้อง,PHA,PHA06,PHA06VB-01,3224CB000000071,"757435.209109,1522886.980549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พนมสารคาม,C2_P,H15101,H15101,C2_P,H05301,,,,,,1,1,,,,,0.011333333,0.011333333,50,5.074532,,,04-01-2025 16:25:22,05-01-2025 07:20:30
         | 
| 64 | 
            +
            4693,5976543217,04-01-2025 16:25:11,1,04-01-2025 16:25:11,04-01-2025 16:25:11,0,0,ไฟฟ้าขัดข้อง,PHA,PHA06,PHA06VB-01,3224CB000000071,"757435.209109,1522886.980549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,พนมสารคาม,C2_P,H15101,H15101,C2_P,H15101,,,,,2133,1775,3908,,,,24.174,20.11666667,44.29066667,27735,5.074532,,,04-01-2025 16:25:22,05-01-2025 07:20:30
         | 
| 65 | 
            +
            4744,5976560250,04-01-2025 17:03:00,1,04-01-2025 17:04:00,04-01-2025 17:04:00,1,1,ไฟฟ้าขัดข้อง,NKP,NKP07,NKP07R-01,32RCHA000003466,"725867.180109,1422207.991549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,มาบตาพุด,C2_P,H14101,H14101,C2_P,H13101,,,,,,1,1,,,,,1,1,30,1.3005388,,,04-01-2025 17:05:28,05-01-2025 07:16:21
         | 
| 66 | 
            +
            4745,5976560250,04-01-2025 17:03:00,1,04-01-2025 17:04:00,04-01-2025 17:04:00,1,1,ไฟฟ้าขัดข้อง,NKP,NKP07,NKP07R-01,32RCHA000003466,"725867.180109,1422207.991549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,วัสดุแปลกปลอม,วัสดุแปลกปลอมอื่นๆ,สายเหนือดิน,สาย,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,เป็นเหตุการณ์ทริปรีโคลส,มาบตาพุด,C2_P,H14101,H14101,C2_P,H14101,,,,,629,,629,,,,629,,629,27020,1.3005388,,,04-01-2025 17:05:28,05-01-2025 07:16:21
         | 
    	
        data/data_3.csv
    ADDED
    
    | The diff for this file is too large to render. 
		See raw diff | 
|  | 
    	
        data/data_3_1.csv
    ADDED
    
    | @@ -0,0 +1,51 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            Number,EventNumber,OutageDateTime,CountOfRestoStep,FirstRestoDateTime,LastRestoDateTime,FirstStepDuration,LastStepDuration,EventType,SubstationID,Feeder,OpDeviceID,OpDeviceGIStag,OpDeviceXYcoord,OpDeviceType,OpDeviceStatus,OpDevicePhase,OpVolt,OpVolt1,OpVolt2,OpDeviceSysType,Owner,FaultSysType,KnowUnknowCause,Weather,FaultDeviceType,FaultDevice,FaultDeviceCondition,Parts,DamagedParts,Manufacturer,RelayType,Relation,RelayPhase,RelayStatus,Detail,FaultDetail,SiteDetail,OpDeviceAreaID,OpDeviceSiteID,EventSiteID,AffectedAreaID,AffectedSiteID,Industrial,AffectedCustomer1,AffectedCustomer2,AffectedCustomer3,AffectedCustomer4,AffectedCustomer5,AffectedCustomer,AllStepCusXTime1,AllStepCusXTime2,AllStepCusXTime3,AllStepCusXTime4,AllStepCusXTime5,AllStepCusXTime,Capacity(kVA),Load(MW),CorrectionDetail,WorkOrderID,CreateEventDateTime,CloseEventDateTime
         | 
| 2 | 
            +
            251,5974274987,1/1/2025 07:20,1,1/1/2025 07:20,1/1/2025 07:20,0.08,0.08,ไฟฟ้าขัดข้อง,LSA,LSA08,LSA04R-01,41RCJA000004946,"511205.822109,1099989.523549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศชื้น / หมอก,สายเหนือดิน,,,ไม่ทราบ,ไม่ทราบ,ไม่มีข้อมูลผู้ผลิต,,,,,,,หลังสวน,S1_P,J13101,J13101,S1_P,J13101,,,,,,890,890,,,,,74.74516667,74.74516667,1390,2.4123716,,,1/1/2025 07:20,1/1/2025 08:04
         | 
| 3 | 
            +
            252,5974274987,1/1/2025 07:20,1,1/1/2025 07:20,1/1/2025 07:20,0.08,0.08,ไฟฟ้าขัดข้อง,LSA,LSA08,LSA04R-01,41RCJA000004946,"511205.822109,1099989.523549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศชื้น / หมอก,สายเหนือดิน,,,ไม่ทราบ,ไม่ทราบ,ไม่มีข้อมูลผู้ผลิต,,,,,,,หลังสวน,S1_P,J13101,J13101,S1_P,J13102,,,,,2865,1062,3927,,,,240.61225,89.1903,329.80255,14375,2.4123716,,,1/1/2025 07:20,1/1/2025 08:04
         | 
| 4 | 
            +
            253,5974275860,1/1/2025 07:20,1,1/1/2025 07:20,1/1/2025 07:20,0.08,0.08,ไฟฟ้าขัดข้อง,WUA,WUA06,WUA06R-04,2142RC000000016,"814842.120109,1913914.464549",Recloser,TR1,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,ไม่ทราบ,ไม่ทราบ,ไม่มีข้อมูลผู้ผลิต,,,Phase ABC,Trip Reclose1,T/R  ,T/R ไม่ทราบสาเหตุ,กฟส.เอราวัณ,NE1_P,D17106,D17106,NE1_P,D11302,,,,,,732,732,,,,,60.268,60.268,730,1.42935,,,1/1/2025 07:20,1/1/2025 08:14
         | 
| 5 | 
            +
            254,5974275860,1/1/2025 07:20,1,1/1/2025 07:20,1/1/2025 07:20,0.08,0.08,ไฟฟ้าขัดข้อง,WUA,WUA06,WUA06R-04,2142RC000000016,"814842.120109,1913914.464549",Recloser,TR1,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,ไม่ทราบ,ไม่ทราบ,ไม่มีข้อมูลผู้ผลิต,,,Phase ABC,Trip Reclose1,T/R  ,T/R ไม่ทราบสาเหตุ,กฟส.เอราวัณ,NE1_P,D17106,D17106,NE1_P,D17106,,,,,174,2821,2995,,,,14.326,232.2623333,246.5883333,11790,1.42935,,,1/1/2025 07:20,1/1/2025 08:14
         | 
| 6 | 
            +
            255,5974276401,1/1/2025 07:21,1,1/1/2025 08:00,1/1/2025 08:00,39,39,ไฟฟ้าขัดข้อง,SRG,SRG03,6000388703-1060050009,6000388703-1060050009,"706969.889109,1621924.118549",Meter,Operate,,Unknown,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,สายไฟฟ้าแรงต่ำ,,,,,,,,,.,C1_P,G03101,G03101,C1_P,G03101,,,,,,,0,,,,,,0,0,0.00024683,,,1/1/2025 07:21,1/1/2025 09:54
         | 
| 7 | 
            +
            256,5974276511,1/1/2025 07:10,1,1/1/2025 07:41,1/1/2025 07:41,31,31,ไฟฟ้าขัดข้อง,LKA,LKA02,51-013497,12XFBA000117611,"599730.348109,1845735.348549",Single Phase Transformer,Operate,AC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,สายไฟฟ้าแรงต่ำ,,,,,Phase A,,,,บ้าน ท่ามะเกลือ,N2_P,B01503,B01503,N2_P,B01503,,,,,,12,12,,,,,372,372,30,0.005446125,,1007875853,1/1/2025 07:22,1/1/2025 07:42
         | 
| 8 | 
            +
            257,5974276549,1/1/2025 07:22,1,1/1/2025 07:22,1/1/2025 07:22,0.08,0.08,ไฟฟ้าขัดข้อง,TMG,TMG02,TMG02WR-101,42RCKA000006219,"421232.857109,920942.224549",Recloser,T/R,ABC,33 kV,33 kV,33 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ส.นก,S2_P,K05301,K05301,S2_P,K05301,,,,,,201,201,,,,,16.7366,16.7366,310,0.061727097,,,1/1/2025 07:22,1/1/2025 07:46
         | 
| 9 | 
            +
            258,5974276590,1/1/2025 06:30,1,1/1/2025 06:55,1/1/2025 06:55,25,25,ไฟฟ้าขัดข้อง,KUR,KUR08,RNA05F-115,41SWJA000003531,"446071.046109,1048275.622549",Drop out Fuse,D/F,ABC,33 kV,33 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,ไลน์นากุ้งเจริญรุ่งเรือง,S1_P,J06105,J06105,S1_P,J06103,,,,,,0,0,,,,,0,0,12000,0.37672986,,1007875856,1/1/2025 07:26,1/1/2025 07:55
         | 
| 10 | 
            +
            259,5974276590,1/1/2025 06:30,1,1/1/2025 06:55,1/1/2025 06:55,25,25,ไฟฟ้าขัดข้อง,KUR,KUR08,RNA05F-115,41SWJA000003531,"446071.046109,1048275.622549",Drop out Fuse,D/F,ABC,33 kV,33 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,ไลน์นากุ้งเจริญรุ่งเรือง,S1_P,J06105,J06105,S1_P,J06105,,,,,,347,347,,,,,8675,8675,4780,0.37672986,,1007875856,1/1/2025 07:26,1/1/2025 07:55
         | 
| 11 | 
            +
            260,5974276857,1/1/2025 07:24,1,1/1/2025 07:24,1/1/2025 07:24,0.02,0.02,ไฟฟ้าขัดข้อง,YTA,YTA06,YTA06VB-01,22CBEA000009086,"1056548.101109,1753538.960549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,ลมแรง,สายเหนือดิน,,,กระบอกฟิวส์,กระบอกฟิวส์,ไม่มีข้อมูลผู้ผลิต,,,,,,,ยส.,NE2_P,E03101,E03101,NE2_P,E03101,,,,2878,668,2560,6106,,,30.9385,7.181,27.52,65.6395,33615,3.4747134,,,1/1/2025 07:24,1/1/2025 07:29
         | 
| 12 | 
            +
            261,5974278053,1/1/2025 07:22,1,1/1/2025 08:01,1/1/2025 08:01,39,39,ไฟฟ้าขัดข้อง,QSA,QSA01,59-024953,4284XF000007592,"509013.850109,936565.274549",Three Phase Transformer,Operate,ABC,33 kV,33 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงสูง,,,,,Phase AB,,,,รายงานสรุปเหตุการณ์ รหัสอุปกรณ์: 59-024953 หมายเลขใบสั่ง: 1007875855 ชนิดฟอร์ท: AB 1Phase to Phase  fault สันนิษฐานสัตว์ สภาพอากาศปกติ(1) อุปกรณ์ที่ใช้:  Fuse link8k (2 เส้น),S2_P,K15102,K15102,S2_P,K15102,,,,,,72,72,,,,,2808,2808,250,0.027345512,,1007875855,1/1/2025 07:24,1/1/2025 08:03
         | 
| 13 | 
            +
            262,5974278348,1/1/2025 07:27,1,1/1/2025 07:40,1/1/2025 07:40,13,13,ไฟฟ้าขัดข้อง,NOA,NOA04,NOA04VF-124,21SWDA000036247,"877847.994109,1817956.845549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,ดรอปเอาท์ฟิวส์,ชำรุด,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,ฟิวส์แรงสูงขาด,ไลน์บ้านยางคำ,NE1_P,D07301,D07301,NE1_P,D07301,,,,,51,,51,,,,663,,663,130,0.015290024,,1007875858,1/1/2025 07:27,1/1/2025 07:46
         | 
| 14 | 
            +
            263,5974278369,1/1/2025 07:26,1,1/1/2025 07:26,1/1/2025 07:26,0.08,0.08,ไฟฟ้าขัดข้อง,DKA,DKA09,DKA05VR-101,1150RC000000054,"514785.684109,2087368.144549",Recloser,T/R,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,รีโคลสเซอร์,,ชุดกลไก สำหรับ ปลด-สับ,ชุดกลไก สำหรับ ปลด-สับ,ไม่มีข้อมูลผู้ผลิต,,,,,,,ไม่ทราบ สาเหตุ ,N1_P,A15201,A15201,N1_P,A15201,,,,,2297,,2297,,,,189.1196667,,189.1196667,14600,1.0051406,,,1/1/2025 07:26,1/1/2025 07:31
         | 
| 15 | 
            +
            264,5974278955,1/1/2025 07:00,1,1/1/2025 07:20,1/1/2025 07:20,20,20,ไฟฟ้าขัดข้อง,PMB,PMB05,6500697589,33PTIA000038539,"641409.283109,1526208.691549",Three Phase Transformer,Operate,ABC,22 kV,22 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงสูง,,,,,,,,,เครื่องวัดกรมยุทธ,C3_P,I18101,I18101,C3_P,I18101,,,,,1,,1,,,,20,,20,30,0.22835956,,1007875857,1/1/2025 07:27,1/1/2025 07:29
         | 
| 16 | 
            +
            265,5974279024,1/1/2025 06:00,1,1/1/2025 08:20,1/1/2025 08:20,140,140,ไฟฟ้าขัดข้อง,BSR,BSR02,BSR02F-023,41SWJA000008310,"549432.708109,1224830.697549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,Fuse - AEG,,,Phase C,,,,ได้รับแจ้งจาก กฟส.บางสะพานน้อยมีไฟดับบริเวณ    ม.4 ซอย บรรตา - ดอนกระทุม ต.บางสะพานน้อย  สาเหตุ  หัวดรอปเอาท์เฟส C ขาด  ทำการปลดฮอลไลน์แคล้มป์ เปลี่ยนอุปกรณ์แรงสูงใหม่   ( สภาพอากาศปกติ )   ,S1_P,J11102,J11102,S1_P,J11102,,,,,60,,60,,,,8400,,8400,310,0.023575142,,1007875859,1/1/2025 07:28,1/1/2025 08:31
         | 
| 17 | 
            +
            266,5974279088,1/1/2025 07:28,1,1/1/2025 07:28,1/1/2025 07:28,0.08,0.08,ไฟฟ้าขัดข้อง,KNI,KNI08,KNI01R-06,22RCEA000006911,"1118343.181109,1700654.210549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,ลมแรง,สายเหนือดิน,,,PIC,เปลือย,ไม่มีข้อมูลผู้ผลิต,,,,,,,จ.อุบลราชธานี,NE2_P,E01101,E01101,NE2_P,E01101,,,,,,347,347,,,,,28.9745,28.9745,600,0.08159491,,,1/1/2025 07:28,1/1/2025 09:19
         | 
| 18 | 
            +
            267,5974279301,1/1/2025 07:27,1,1/1/2025 08:30,1/1/2025 08:30,63,63,ไฟฟ้าขัดข้อง,SBY,SBY07,SBY07WF-115,43SWLA000074527,"704633.803109,742489.916549",Drop out Fuse,D/F,C,33 kV,33 kV,33 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,512160  ไฟดับบ้านควนหมาก ม.3 ต.วังใหญ่ อ.เทพา ตรวจสอบพบฟิวส์แรงสูงขาด DF ชำรุด เคลียร์ไลน์พบสาเหตุ ต้นมะพร้าวล้มทับสายแรงสูง ,S3_P,L13401,L13401,S3_P,L13401,,,,,,26,26,,,,,1638,1638,30,0.010800272,,1007875860,1/1/2025 07:30,1/1/2025 08:52
         | 
| 19 | 
            +
            268,5974279336,1/1/2025 07:31,1,1/1/2025 07:33,1/1/2025 07:33,2,2,ไฟฟ้าขัดข้อง,LBL,LBL04,6001560112-1060050001,6001560112-1060050001,"636815.781108,1561895.953549",Meter,Operate,,Unknown,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,จุดต่อสายแรงต่ำ,,,,,,,,,ม.7,C3_P,I14102,I14102,C3_P,I14102,,,,,,1,1,,,,,2,2,,0.001066576,,1007875862,1/1/2025 07:31,1/1/2025 07:34
         | 
| 20 | 
            +
            269,5974279432,1/1/2025 07:32,1,1/1/2025 07:32,1/1/2025 07:32,0.08,0.08,ไฟฟ้าขัดข้อง,SWA,SWA04,SWA04VR-04,12RCBA000011274,"581983.835109,1904250.804549",Recloser,T/R,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศชื้น / หมอก,สายเหนือดิน,,,ไม่ทราบ,ไม่ทราบ,ไม่มีข้อมูลผู้ผลิต,,,Phase C,,,, ตรวจสอบระบบจำหน่ายไม่พบสาเหตุ ,N2_P,B11101,B11101,N2_P,B11101,,,,,1432,215,1647,,,,124.2976,18.662,142.9596,2690,0.42893198,,,1/1/2025 07:32,1/1/2025 08:07
         | 
| 21 | 
            +
            270,5974280888,1/1/2025 07:34,1,1/1/2025 07:34,1/1/2025 07:34,0,0,ไฟฟ้าขัดข้อง,NUA,NUA03,NUA03VB-01,13CBCA000005272,"676631.652109,1687428.282549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,เปลือย,เปลือย,ไม่มีข้อมูลผู้ผลิต,,,,,,,"""บ้านยางโทน,บ้านหนองอีเก้ง,อ.โคกเจริญ(บางส่วน) (ไม่มี รพ.ได้รับผลกระทบ)/T/R1/พบสาเหตุเกิดจาก D/F เฟส B ชำรุด บริเวณบ้านหนองทอง""",N3_P,C08501,C08501,N3_P,C08101,,,,,,,0,,,,,,0,0,2.991932,,,1/1/2025 07:34,1/1/2025 07:43
         | 
| 22 | 
            +
            271,5974280888,1/1/2025 07:34,1,1/1/2025 07:34,1/1/2025 07:34,0,0,ไฟฟ้าขัดข้อง,NUA,NUA03,NUA03VB-01,13CBCA000005272,"676631.652109,1687428.282549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,เปลือย,เปลือย,ไม่มีข้อมูลผู้ผลิต,,,,,,,"""บ้านยางโทน,บ้านหนองอีเก้ง,อ.โคกเจริญ(บางส่วน) (ไม่มี รพ.ได้รับผลกระทบ)/T/R1/พบสาเหตุเกิดจาก D/F เฟส B ชำรุด บริเวณบ้านหนองทอง""",N3_P,C08501,C08501,N3_P,C08501,,,,,45,2793,2838,,,,0.48,29.792,30.272,9240,2.991932,,,1/1/2025 07:34,1/1/2025 07:43
         | 
| 23 | 
            +
            272,5974280888,1/1/2025 07:34,1,1/1/2025 07:34,1/1/2025 07:34,0,0,ไฟฟ้าขัดข้อง,NUA,NUA03,NUA03VB-01,13CBCA000005272,"676631.652109,1687428.282549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,เปลือย,เปลือย,ไม่มีข้อมูลผู้ผลิต,,,,,,,"""บ้านยางโทน,บ้านหนองอีเก้ง,อ.โคกเจริญ(บางส่วน) (ไม่มี รพ.ได้รับผลกระทบ)/T/R1/พบสาเหตุเกิดจาก D/F เฟส B ชำรุด บริเวณบ้านหนองทอง""",N3_P,C08501,C08501,N3_P,C08502,,,,,,5155,5155,,,,,54.98666667,54.98666667,9445,2.991932,,,1/1/2025 07:34,1/1/2025 07:43
         | 
| 24 | 
            +
            273,5974284316,1/1/2025 06:45,1,1/1/2025 08:19,1/1/2025 08:19,94,94,ไฟฟ้าขัดข้อง,WVA,WVA03,LRA09F-91,42SWKA000048633,"539276.642109,868637.886549",Drop out Fuse,D/F,B,33 kV,33 kV,33 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,รับเเจ้งไฟดับ บ้านไชยภักดี สาเหตุ ช็อตสัตว์ อุปกรณ์ที่ใช้:  Fuse link30k (1 เส้น),S2_P,K17102,K17102,S2_P,K17102,,,,,,124,124,,,,,11656,11656,150,0.018602335,,1007875866,1/1/2025 07:36,1/1/2025 08:20
         | 
| 25 | 
            +
            274,5974284397,1/1/2025 06:50,1,1/1/2025 07:34,1/1/2025 07:34,44,44,ไฟฟ้าขัดข้อง,BUY,BUY06,BUY06VF-312,23SWFA000105976,"880074.033109,1707155.028549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,Phase C,,หน้า อ.โนนแดง ฟิวส์ป้องกันไลน์ขาดเฟส C สับเปลี่ยนฟิวส์ทดลองจ่ายไฟได้ปกติ,หน้า อ.โนนแดง ฟิวส์ป้องกันไลน์ขาดเฟส C สับเปลี่ยนฟิวส์ทดลองจ่ายไฟได้ปกติ,หน้า อ.โนนแดง ,NE3_P,F08202,F08202,NE3_P,F08202,,,,,45,1008,1053,,,,1980,44352,46332,1130,1.525149,,1007875867,1/1/2025 07:36,1/1/2025 08:36
         | 
| 26 | 
            +
            275,5974285372,1/1/2025 07:36,1,1/1/2025 07:39,1/1/2025 07:39,3,3,ไฟฟ้าขัดข้อง,SPN,SPN05,58-012941,33XFIA000075317,"621824.305109,1561732.160549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงต่ำ,,,,,,,,,ม.16,C3_P,I14102,I14102,C3_P,I14102,,,,,,54,54,,,,,162,162,100,0.02227634,,1007875868,1/1/2025 07:36,1/1/2025 07:39
         | 
| 27 | 
            +
            276,5974285432,1/1/2025 07:00,1,1/1/2025 07:30,1/1/2025 07:30,30,30,ไฟฟ้าขัดข้อง,XNA,XNA09,65-001745,2330XF000009334,"803839.576109,1630603.082549",Three Phase Transformer,Operate,ABC,22 kV,22 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงสูง,,,,,,,,,DCC_บ.หนองเลาใหญ่ (คลอนแคลน),NE3_P,F07201,F07201,NE3_P,F07201,,,,,,49,49,,,,,1470,1470,50,0.0100065,,1007875869,1/1/2025 07:39,1/1/2025 07:41
         | 
| 28 | 
            +
            277,5974285606,1/1/2025 07:29,1,1/1/2025 07:29,1/1/2025 07:29,0,0,ไฟฟ้าขัดข้อง,BLS,BLS06,BLS06VB-01,31CBGA000000679,"679627.210109,1571063.126549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ตัว Circuit breaker,ตัว Circuit breaker,ไม่มีข้อมูลผู้ผลิต,,,,,,,T/R ไม่มีไฟดับ,C1_P,G24101,G24101,C1_P,G24101,,,,,,9,9,,,,,0,0,2725,0.41593845,,,1/1/2025 07:38,1/1/2025 13:11
         | 
| 29 | 
            +
            278,5974285687,1/1/2025 07:38,1,1/1/2025 07:38,1/1/2025 07:38,0.08,0.08,ไฟฟ้าขัดข้อง,KRA,KRA05,KRA05VR-101,2140RC000000058,"913521.763109,1851611.308549",Recloser,TR1,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,ไม่ทราบ,ไม่ทราบ,ไม่มีข้อมูลผู้ผลิต,,,Phase AG,Trip Reclose1,T/R  ,T/R ไม่ทราบสาเหตุ,กฟส.น้ำพอง,NE1_P,D03201,D03201,NE1_P,D03201,,,,,,6136,6136,,,,,513.3786667,513.3786667,8600,1.2389691,,,1/1/2025 07:38,1/1/2025 08:15
         | 
| 30 | 
            +
            279,5974286282,1/1/2025 07:39,1,1/1/2025 07:57,1/1/2025 07:57,18,18,ไฟฟ้าขัดข้อง,ANA,ANA05,ANA05VF-043,22SWEA000221894,"1092707.393109,1754939.631549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,ลมแรง,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,บ.คำสร้างบ่อ,NE2_P,E08101,E08101,NE2_P,E08101,,,,,,52,52,,,,,936,936,350,0.013441769,,1007875873,1/1/2025 07:39,1/1/2025 07:58
         | 
| 31 | 
            +
            280,5974286358,1/1/2025 07:20,1,1/1/2025 07:40,1/1/2025 07:40,20,20,ไฟฟ้าขัดข้อง,PEA,PEA02,64-008964,13XFCA000081773,"723829.147109,1808884.171549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงต่ำ,,,,,,,,,บ้านโตก,N3_P,C06101,C06101,N3_P,C06101,,,,,,2,2,,,,,40,40,100,0.000267663,,1007875871,1/1/2025 07:39,1/1/2025 07:49
         | 
| 32 | 
            +
            281,5974286502,1/1/2025 07:39,1,1/1/2025 08:00,1/1/2025 08:00,21,21,ไฟฟ้าขัดข้อง,QKA,QKA04,QKA04VF-260,23SWFA000058976,"818569.164109,1811305.289549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,ดรอปเอาท์ฟิวส์,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,Phase B,,,,ไลน์บึงแก้ง,NE3_P,F11201,F11201,NE3_P,F11201,,,,,,12,12,,,,,252,252,810,0.001326415,,1007875870,1/1/2025 07:39,1/1/2025 08:22
         | 
| 33 | 
            +
            282,5974286532,1/1/2025 06:34,2,1/1/2025 07:20,1/1/2025 07:20,45.05,45.05,ไฟฟ้าขัดข้อง,BSP,BSP02,50-007299,41XFJA000088483,"570296.556109,1280750.554549",Three Phase Transformer,Operate,ABC,22 kV,22 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,หม้อแปลงจำหน่าย,,,หม้อแปลงจำหน่าย,,,,,Phase AB,,,,หนองครก / เปลี่ยนฟิวส์แรงสูง,S1_P,J04301,J04301,S1_P,J04301,,,,,,22,22,,,,,885.0442,885.0442,50,0.013401268,,1007875872,1/1/2025 07:39,1/1/2025 07:50
         | 
| 34 | 
            +
            283,5974286813,1/1/2025 07:20,1,1/1/2025 07:42,1/1/2025 07:42,22,22,ไฟฟ้าขัดข้อง,CON,CON05,56-004918,13XFCA000022111,"705727.950109,1808367.465549",Single Phase Transformer,Operate,AC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,จุดต่อสายแรงต่ำ,,,,,,,,,บ้านซับเปิบ,N3_P,C06201,C06201,N3_P,C06201,,,,,,56,56,,,,,1232,1232,30,0.007835598,,1007875874,1/1/2025 07:41,1/1/2025 07:52
         | 
| 35 | 
            +
            284,5974287458,1/1/2025 07:20,1,1/1/2025 07:42,1/1/2025 07:42,22,22,ไฟฟ้าขัดข้อง,CON,CON04,37-001296,1367XF000000341,"707276.977109,1796954.112549",Single Phase Transformer,Operate,AC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,จุดต่อสายแรงต่ำ,,,,,,,,,บ้านอ่างหิน,N3_P,C06201,C06201,N3_P,C06201,,,,,,57,57,,,,,1254,1254,30,0.010892663,,1007875875,1/1/2025 07:42,1/1/2025 07:55
         | 
| 36 | 
            +
            285,5974287524,1/1/2025 07:00,1,1/1/2025 07:30,1/1/2025 07:30,30,30,ไฟฟ้าขัดข้อง,UAA,UAA06,UAA06F-19,13SWCA000062715,"617621.798109,1695544.969549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,บ.ตาลเอน,N3_P,C03101,C03101,N3_P,C03101,,,,,,412,412,,,,,12360,12360,500,0.065601234,,1007875876,1/1/2025 07:42,1/1/2025 07:45
         | 
| 37 | 
            +
            286,5974287591,1/1/2025 07:30,1,1/1/2025 07:45,1/1/2025 07:45,15,15,ไฟฟ้าขัดข้อง,DAA,DAA06,DAA09F-07,3372SW000000538,"575846.289109,1637847.137549",Drop out Fuse,D/F,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,Phase A,,,,ไลน์แยกแตงโม ,C3_P,I13301,I13301,C3_P,I13301,,,,,,164,164,,,,,2460,2460,780,0.037147697,,1007875877,1/1/2025 07:44,1/1/2025 07:58
         | 
| 38 | 
            +
            287,5974287638,1/1/2025 07:43,1,1/1/2025 08:00,1/1/2025 08:00,17,17,ไฟฟ้าขัดข้อง,SRG,SRG03,6100888649-1060050009,6100888649-1060050009,"706976.303109,1621924.382549",Meter,Operate,,Unknown,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,สายไฟฟ้าแรงต่ำ,,,,,,,,,.,C1_P,G03101,G03101,C1_P,G03101,,,,,,,0,,,,,,0,0,0.000241395,,,1/1/2025 07:43,1/1/2025 09:54
         | 
| 39 | 
            +
            288,5974289895,1/1/2025 07:45,1,1/1/2025 07:45,1/1/2025 07:45,0.08,0.08,ไฟฟ้าขัดข้อง,SFB,SFB05,SFB05VR-201,2330RC000000001,"776245.846109,1643913.974549",Recloser,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,OHGW,OHGW,ไม่มีข้อมูลผู้ผลิต,,,Phase AC,,,,T/R ไม่ทราบสาเหตุ,NE3_P,F07101,F07101,NE3_P,F07101,,,,,4040,3901,7941,,,,338.0133333,326.3836667,664.397,22995,2.462084,,,1/1/2025 07:45,1/1/2025 09:33
         | 
| 40 | 
            +
            289,5974291677,1/1/2025 07:35,1,1/1/2025 08:28,1/1/2025 08:28,53,53,ไฟฟ้าขัดข้อง,KGA,KGA02,KGA06F-21,2330SW000000913,"894492.682109,1706541.074549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,Phase A,,,,ไลน์บ้���นโนนกระเพรา,NE3_P,F10101,F10101,NE3_P,F10101,,,,,,59,59,,,,,3127,3127,80,0.013643484,สัตว์ : เปลี่ยนฟิวส์ Link,1007875878,1/1/2025 07:45,1/1/2025 08:35
         | 
| 41 | 
            +
            290,5974293710,1/1/2025 07:45,1,1/1/2025 07:56,1/1/2025 07:56,11,11,ไฟฟ้าขัดข้อง,NCH,NCH05,MRA04F-27,13SWCA000060024,"589258.952109,1689010.392549",Drop out Fuse,D/F,AB,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,, บ้านหนองยาง,N3_P,C04602,C04602,N3_P,C04602,,,,,168,,168,,,,1848,,1848,160,0.02759504,,1007875879,1/1/2025 07:45,1/1/2025 07:57
         | 
| 42 | 
            +
            291,5974295843,1/1/2025 07:46,1,1/1/2025 07:46,1/1/2025 07:46,0.08,0.08,ไฟฟ้าขัดข้อง,NTB,NTB02,NTB02WR-102,42RCKA000009025,"602215.038109,947217.965549",Recloser,T/R,ABC,33 kV,33 kV,33 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,SAC,SAC,ไม่มีข้อมูลผู้ผลิต,,,,,,,ส.นก,S2_P,K16101,K16101,S2_P,K16101,,,,,,2339,2339,,,,,196.1641333,196.1641333,2510,0.6150933,,,1/1/2025 07:46,1/1/2025 09:21
         | 
| 43 | 
            +
            292,5974296108,1/1/2025 07:46,1,1/1/2025 08:34,1/1/2025 08:34,48,48,ไฟฟ้าขัดข้อง,PJA,PJA02,60-016859,31XFGA000082940,"682631.443109,1624103.890549",Three Phase Transformer,Operate,ABC,22 kV,22 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,หม้อแปลงจำหน่าย,,,หม้อแปลงจำหน่าย,,,,,,,,,หนองโดน,C1_P,G10103,G10103,C1_P,G10103,,,,,52,,52,,,,2496,,2496,100,0.011461833,,1007875880,1/1/2025 07:46,1/1/2025 08:35
         | 
| 44 | 
            +
            293,5974296325,1/1/2025 07:48,1,1/1/2025 07:48,1/1/2025 07:48,0,0,ไฟฟ้าขัดข้อง,PCB,PCB06,PCB06VB-01,23CBFA000001116,"748664.685109,1621240.562549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,OHGW,PIC,ไม่มีข้อมูลผู้ผลิต,,,Phase AG,,,,T/R ไม่ทราบสาเหตุ,NE3_P,F06102,F06102,NE3_P,F06101,,,,,2,88,90,,,,0.022466667,0.988533333,1.011,11615,3.1105884,,,1/1/2025 07:48,1/1/2025 11:45
         | 
| 45 | 
            +
            294,5974296325,1/1/2025 07:48,1,1/1/2025 07:48,1/1/2025 07:48,0,0,ไฟฟ้าขัดข้อง,PCB,PCB06,PCB06VB-01,23CBFA000001116,"748664.685109,1621240.562549",Circuit Breaker_MV,T/R,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,OHGW,PIC,ไม่มีข้อมูลผู้ผลิต,,,Phase AG,,,,T/R ไม่ทราบสาเหตุ,NE3_P,F06102,F06102,NE3_P,F06102,,,,,0,,0,,,,0,,0,160,3.1105884,,,1/1/2025 07:48,1/1/2025 11:45
         | 
| 46 | 
            +
            295,5974296865,1/1/2025 07:49,1,1/1/2025 08:15,1/1/2025 08:15,26,26,ไฟฟ้าขัดข้อง,KCA,KCA09,52-004487,3371XF000004834,"558422.054109,1549426.942549",Three Phase Transformer,Operate,ABC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,สายเหนือดิน,,,สายไฟฟ้าแรงต่ำ,,,,,,,,,ซอยไปรษณีย์,C3_P,I03101,I03101,C3_P,I03101,,,,82,,,82,,,2132,,,2132,160,0.05334112,,1007875881,1/1/2025 07:49,1/1/2025 08:15
         | 
| 47 | 
            +
            296,5974297507,1/1/2025 07:15,1,1/1/2025 07:45,1/1/2025 07:45,30,30,ไฟฟ้าขัดข้อง,PSU,PSU03,54-017406,23XFFA000009393,"976471.927109,1625324.023549",Single Phase Transformer,Operate,AC,22 kV,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,ไม่พบสาเหตุ,อากาศปกติ,หม้อแปลงจำหน่าย,,,หม้อแปลงจำหน่าย,,,,,,,,,DCC_บ้านสัมพันธ์(กลุ่มนอก),NE3_P,F12101,F12101,NE3_P,F12101,,,,,,27,27,,,,,810,810,30,0.005457014,,1007875882,1/1/2025 07:50,1/1/2025 08:09
         | 
| 48 | 
            +
            297,5974297587,1/1/2025 07:51,1,1/1/2025 08:16,1/1/2025 08:16,25,25,ไฟฟ้าขัดข้อง,KCA,KCA03,27668822,33PTIA000041917,"552764.317109,1554760.264549",Three Phase Transformer,Operate,ABC,22 kV,22 kV,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,ฟิวส์แรงสูง,,,,,,,,,สนง ขนส่ง,C3_P,I03101,I03101,C3_P,I03101,,,,,1,,1,,,,25,,25,30,0.019874548,,1007875883,1/1/2025 07:51,1/1/2025 08:16
         | 
| 49 | 
            +
            298,5974297731,1/1/2025 07:52,1,1/1/2025 08:05,1/1/2025 08:05,13,13,ไฟฟ้าขัดข้อง,BNP,BNP08,BNP08F-12,33SWIA000054553,"618058.516109,1502573.775549",Drop out Fuse,D/F,ABC,22 kV,22 kV,220 V,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,Circuit Breaker - SPERCHER  ENERGIE,,,,,,,บ้านแพ้ว,C3_P,I16101,I16101,C3_P,I16101,,,,,58,,58,,,,754,,754,260,0.04843949,,1007875884,1/1/2025 07:52,1/1/2025 08:07
         | 
| 50 | 
            +
            299,5974297805,1/1/2025 07:52,1,1/1/2025 08:44,1/1/2025 08:44,52,52,ไฟฟ้าขัดข้อง,CYA,CYA05,6100582030-1060050001,6100582030-1060050001,"821267.142108,1725242.149549",Meter,Operate,,Unknown,220 V,,ระบบจำหน่ายแรงต่ำ,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศชื้น / หมอก,อุปกรณ์ป้องกันและตัดตอน,,,LT สวิตซ์แรงต่ำ,,,,,,,,,-21 บ.บะเสียว ม.6 ต.หนองฉิม อ.เ,NE3_P,F02306,F02306,NE3_P,F02306,,,,,,1,1,,,,,52,52,,0.000365036,,1007875885,1/1/2025 07:52,1/1/2025 10:44
         | 
| 51 | 
            +
            300,5974297900,1/1/2025 07:10,1,1/1/2025 07:30,1/1/2025 07:30,20,20,ไฟฟ้าขัดข้อง,CTB,CTB09,CTA01F-20,3222SW000000576,"842091.815109,1394115.812549",Drop out Fuse,D/F,ABC,22 kV,22 kV,22 kV,ระบบจำหน่ายแรงสูง,กฟภ.-ไฟฟ้าขัดข้อง,ระบบจำหน่าย,พบสาเหตุ,อากาศปกติ,อุปกรณ์ป้องกันและตัดตอน,,,Fuse link,Fuse link,ไม่มีข้อมูลผู้ผลิต,,,,,,,ซอยวัดทองทั่ว,C2_P,H03101,H03101,C2_P,H03101,,,,,741,555,1296,,,,14820,11100,25920,2840,0.45207108,,1007875886,1/1/2025 07:53,1/1/2025 07:58
         | 
    	
        requirements.txt
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            pandas==2.2.2
         | 
| 2 | 
            +
            numpy==1.26.4
         | 
| 3 | 
            +
            python-dateutil==2.8.2
         | 
| 4 | 
            +
            jinja2==3.1.2
         | 
| 5 | 
            +
            scikit-learn==1.3.2
         | 
| 6 | 
            +
            pydantic==2.11.7
         | 
| 7 | 
            +
            matplotlib==3.8.1
         | 
| 8 | 
            +
            seaborn==0.12.2
         | 
| 9 | 
            +
            geopandas==0.13.2
         | 
| 10 | 
            +
            shapely==2.1.1
         | 
| 11 | 
            +
            fsspec==2024.9.0
         | 
| 12 | 
            +
            tensorflow==2.16.1
         | 
| 13 | 
            +
            gradio==3.44.0
         | 
| 14 | 
            +
            fastapi==0.115.14
         | 
| 15 | 
            +
            openai==1.109.1
         | 
| 16 | 
            +
            python-dotenv==1.0.0
         | 
| 17 | 
            +
            prophet==1.1.7
         | 
| 18 | 
            +
            uvicorn==0.20.0
         | 
| 19 | 
            +
            websockets==11.0.3
         | 
| 20 | 
            +
            huggingface-hub==0.35.1
         | 
| 21 | 
            +
            httpx==0.28.1
         | 
| 22 | 
            +
            orjson==3.11.3
         | 
| 23 | 
            +
            cmdstanpy==1.2.5
         | 
| 24 | 
            +
            stanio==0.5.1
         | 
    	
        scripts/anomaly.py
    ADDED
    
    | @@ -0,0 +1,193 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import pandas as pd
         | 
| 2 | 
            +
            import numpy as np
         | 
| 3 | 
            +
            from sklearn.ensemble import IsolationForest
         | 
| 4 | 
            +
            from sklearn.neighbors import LocalOutlierFactor
         | 
| 5 | 
            +
            from sklearn.preprocessing import StandardScaler
         | 
| 6 | 
            +
            from typing import Tuple
         | 
| 7 | 
            +
            try:
         | 
| 8 | 
            +
                import tensorflow as tf
         | 
| 9 | 
            +
                from tensorflow.keras import layers, models
         | 
| 10 | 
            +
                TF_AVAILABLE = True
         | 
| 11 | 
            +
            except ImportError:
         | 
| 12 | 
            +
                TF_AVAILABLE = False
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            def parse_datetime_cols(df: pd.DataFrame) -> pd.DataFrame:
         | 
| 16 | 
            +
                for c in ['OutageDateTime','FirstRestoDateTime','LastRestoDateTime']:
         | 
| 17 | 
            +
                    if c in df.columns:
         | 
| 18 | 
            +
                        df[c+'_dt'] = pd.to_datetime(df[c], format='%d-%m-%Y %H:%M:%S', errors='coerce')
         | 
| 19 | 
            +
                return df
         | 
| 20 | 
            +
             | 
| 21 | 
            +
             | 
| 22 | 
            +
            def feature_engineer(df: pd.DataFrame) -> pd.DataFrame:
         | 
| 23 | 
            +
                df = df.copy()
         | 
| 24 | 
            +
                df = parse_datetime_cols(df)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # Duration in minutes between outage and last restore
         | 
| 27 | 
            +
                if 'OutageDateTime_dt' in df.columns and 'LastRestoDateTime_dt' in df.columns:
         | 
| 28 | 
            +
                    df['duration_min'] = (df['LastRestoDateTime_dt'] - df['OutageDateTime_dt']).dt.total_seconds() / 60.0
         | 
| 29 | 
            +
                else:
         | 
| 30 | 
            +
                    df['duration_min'] = np.nan
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                # Load numeric
         | 
| 33 | 
            +
                for col in ['Load(MW)','Capacity(kVA)','FirstStepDuration','LastStepDuration','AffectedCustomer']:
         | 
| 34 | 
            +
                    if col in df.columns:
         | 
| 35 | 
            +
                        df[col+'_num'] = pd.to_numeric(df[col], errors='coerce')
         | 
| 36 | 
            +
                    else:
         | 
| 37 | 
            +
                        df[col+'_num'] = np.nan
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                # time of day
         | 
| 40 | 
            +
                if 'OutageDateTime_dt' in df.columns:
         | 
| 41 | 
            +
                    df['hour'] = df['OutageDateTime_dt'].dt.hour
         | 
| 42 | 
            +
                else:
         | 
| 43 | 
            +
                    df['hour'] = np.nan
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                # device type one-hot small encoding: frequency
         | 
| 46 | 
            +
                if 'OpDeviceType' in df.columns:
         | 
| 47 | 
            +
                    freq = df['OpDeviceType'].fillna('NA').value_counts()
         | 
| 48 | 
            +
                    df['device_freq'] = df['OpDeviceType'].map(lambda x: freq.get(x,0))
         | 
| 49 | 
            +
                else:
         | 
| 50 | 
            +
                    df['device_freq'] = 0
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                # coordinates
         | 
| 53 | 
            +
                if 'OpDeviceXYcoord' in df.columns:
         | 
| 54 | 
            +
                    def parse_xy(s):
         | 
| 55 | 
            +
                        try:
         | 
| 56 | 
            +
                            s = str(s).strip().strip('"')
         | 
| 57 | 
            +
                            x,y = s.split(',')
         | 
| 58 | 
            +
                            return float(x), float(y)
         | 
| 59 | 
            +
                        except Exception:
         | 
| 60 | 
            +
                            return (np.nan, np.nan)
         | 
| 61 | 
            +
                    xs, ys = zip(*df['OpDeviceXYcoord'].map(parse_xy))
         | 
| 62 | 
            +
                    df['x'] = xs
         | 
| 63 | 
            +
                    df['y'] = ys
         | 
| 64 | 
            +
                else:
         | 
| 65 | 
            +
                    df['x'] = np.nan
         | 
| 66 | 
            +
                    df['y'] = np.nan
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                return df
         | 
| 69 | 
            +
             | 
| 70 | 
            +
             | 
| 71 | 
            +
            def build_feature_matrix(df: pd.DataFrame) -> Tuple[np.ndarray, list]:
         | 
| 72 | 
            +
                df_fe = feature_engineer(df)
         | 
| 73 | 
            +
                features = ['duration_min','Load(MW)_num','AffectedCustomer_num','hour','device_freq','x','y']
         | 
| 74 | 
            +
                X = df_fe[features].copy()
         | 
| 75 | 
            +
                # Fill na with median
         | 
| 76 | 
            +
                X = X.fillna(X.median())
         | 
| 77 | 
            +
                scaler = StandardScaler()
         | 
| 78 | 
            +
                Xs = scaler.fit_transform(X)
         | 
| 79 | 
            +
                return Xs, features, df_fe, scaler
         | 
| 80 | 
            +
             | 
| 81 | 
            +
             | 
| 82 | 
            +
            def run_isolation_forest(X: np.ndarray, contamination: float = 0.05, random_state: int = 42):
         | 
| 83 | 
            +
                iso = IsolationForest(contamination=contamination, random_state=random_state)
         | 
| 84 | 
            +
                preds = iso.fit_predict(X)
         | 
| 85 | 
            +
                # IsolationForest returns -1 for outliers
         | 
| 86 | 
            +
                scores = iso.decision_function(X)
         | 
| 87 | 
            +
                return preds, scores
         | 
| 88 | 
            +
             | 
| 89 | 
            +
             | 
| 90 | 
            +
            def run_lof(X: np.ndarray, contamination: float = 0.05, n_neighbors: int = 20):
         | 
| 91 | 
            +
                lof = LocalOutlierFactor(n_neighbors=n_neighbors, contamination=contamination)
         | 
| 92 | 
            +
                preds = lof.fit_predict(X)
         | 
| 93 | 
            +
                # negative_outlier_factor_ (the lower, more abnormal)
         | 
| 94 | 
            +
                scores = lof.negative_outlier_factor_
         | 
| 95 | 
            +
                return preds, scores
         | 
| 96 | 
            +
             | 
| 97 | 
            +
             | 
| 98 | 
            +
            def run_autoencoder(X: np.ndarray, contamination: float = 0.05, latent_dim: int = 4, epochs: int = 50, batch_size: int = 32):
         | 
| 99 | 
            +
                if not TF_AVAILABLE:
         | 
| 100 | 
            +
                    raise ImportError("TensorFlow not available. Install tensorflow to use autoencoder.")
         | 
| 101 | 
            +
                
         | 
| 102 | 
            +
                input_dim = X.shape[1]
         | 
| 103 | 
            +
                
         | 
| 104 | 
            +
                # Build autoencoder
         | 
| 105 | 
            +
                encoder = models.Sequential([
         | 
| 106 | 
            +
                    layers.Input(shape=(input_dim,)),
         | 
| 107 | 
            +
                    layers.Dense(16, activation='relu'),
         | 
| 108 | 
            +
                    layers.Dense(latent_dim, activation='relu')
         | 
| 109 | 
            +
                ])
         | 
| 110 | 
            +
                
         | 
| 111 | 
            +
                decoder = models.Sequential([
         | 
| 112 | 
            +
                    layers.Input(shape=(latent_dim,)),
         | 
| 113 | 
            +
                    layers.Dense(16, activation='relu'),
         | 
| 114 | 
            +
                    layers.Dense(input_dim, activation='linear')
         | 
| 115 | 
            +
                ])
         | 
| 116 | 
            +
                
         | 
| 117 | 
            +
                autoencoder = models.Sequential([encoder, decoder])
         | 
| 118 | 
            +
                autoencoder.compile(optimizer='adam', loss='mse')
         | 
| 119 | 
            +
                
         | 
| 120 | 
            +
                # Train
         | 
| 121 | 
            +
                autoencoder.fit(X, X, epochs=epochs, batch_size=batch_size, verbose=0, validation_split=0.1)
         | 
| 122 | 
            +
                
         | 
| 123 | 
            +
                # Reconstruction error
         | 
| 124 | 
            +
                reconstructed = autoencoder.predict(X, verbose=0)
         | 
| 125 | 
            +
                mse = np.mean((X - reconstructed)**2, axis=1)
         | 
| 126 | 
            +
                
         | 
| 127 | 
            +
                # Threshold based on contamination
         | 
| 128 | 
            +
                threshold = np.percentile(mse, (1 - contamination) * 100)
         | 
| 129 | 
            +
                preds = (mse > threshold).astype(int) * -1  # -1 for outliers
         | 
| 130 | 
            +
                preds[preds == 0] = 1  # 1 for inliers
         | 
| 131 | 
            +
                
         | 
| 132 | 
            +
                return preds, mse
         | 
| 133 | 
            +
             | 
| 134 | 
            +
             | 
| 135 | 
            +
            def explain_anomalies(df_fe: pd.DataFrame, explain_features=None):
         | 
| 136 | 
            +
                # explain_features: which numeric columns to compute z-score on
         | 
| 137 | 
            +
                if explain_features is None:
         | 
| 138 | 
            +
                    explain_features = ['duration_min','Load(MW)_num','AffectedCustomer_num','hour','device_freq']
         | 
| 139 | 
            +
                df_num = df_fe[explain_features].astype(float).fillna(df_fe[explain_features].median())
         | 
| 140 | 
            +
                means = df_num.mean()
         | 
| 141 | 
            +
                stds = df_num.std().replace(0, 1.0)
         | 
| 142 | 
            +
                z = (df_num - means) / stds
         | 
| 143 | 
            +
                # create explanation string for each row: top 3 absolute z-scores
         | 
| 144 | 
            +
                explanations = []
         | 
| 145 | 
            +
                for i, row in z.iterrows():
         | 
| 146 | 
            +
                    abs_row = row.abs()
         | 
| 147 | 
            +
                    top = abs_row.sort_values(ascending=False).head(3)
         | 
| 148 | 
            +
                    parts = []
         | 
| 149 | 
            +
                    for feat in top.index:
         | 
| 150 | 
            +
                        val = row[feat]
         | 
| 151 | 
            +
                        sign = 'สูง' if val > 0 else 'ต่ำ' if val < 0 else 'ปกติ'
         | 
| 152 | 
            +
                        parts.append(f"{feat} {sign} (z={val:.2f})")
         | 
| 153 | 
            +
                    explanations.append('; '.join(parts))
         | 
| 154 | 
            +
                return z, explanations
         | 
| 155 | 
            +
             | 
| 156 | 
            +
             | 
| 157 | 
            +
            def detect_anomalies(df: pd.DataFrame, contamination: float = 0.05, algorithm: str = 'both') -> pd.DataFrame:
         | 
| 158 | 
            +
                Xs, features, df_fe, scaler = build_feature_matrix(df)
         | 
| 159 | 
            +
                
         | 
| 160 | 
            +
                if algorithm == 'autoencoder':
         | 
| 161 | 
            +
                    preds, scores = run_autoencoder(Xs, contamination=contamination)
         | 
| 162 | 
            +
                    res = df.copy().reset_index(drop=True)
         | 
| 163 | 
            +
                    res['auto_pred'] = preds
         | 
| 164 | 
            +
                    res['auto_score'] = scores
         | 
| 165 | 
            +
                    res['final_flag'] = res['auto_pred'] == -1
         | 
| 166 | 
            +
                else:
         | 
| 167 | 
            +
                    preds_iso, scores_iso = run_isolation_forest(Xs, contamination=contamination)
         | 
| 168 | 
            +
                    preds_lof, scores_lof = run_lof(Xs, contamination=contamination)
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                    res = df.copy().reset_index(drop=True)
         | 
| 171 | 
            +
                    res['iso_pred'] = preds_iso
         | 
| 172 | 
            +
                    res['iso_score'] = scores_iso
         | 
| 173 | 
            +
                    res['lof_pred'] = preds_lof
         | 
| 174 | 
            +
                    res['lof_score'] = scores_lof
         | 
| 175 | 
            +
                    # ensemble: flag if both mark as outlier (-1)
         | 
| 176 | 
            +
                    res['ensemble_flag'] = ((res['iso_pred'] == -1) & (res['lof_pred'] == -1))
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                    # algorithm filter: if algorithm == 'iso' or 'lof' or 'both', compute final_flag
         | 
| 179 | 
            +
                    if algorithm == 'iso':
         | 
| 180 | 
            +
                        res['final_flag'] = res['iso_pred'] == -1
         | 
| 181 | 
            +
                    elif algorithm == 'lof':
         | 
| 182 | 
            +
                        res['final_flag'] = res['lof_pred'] == -1
         | 
| 183 | 
            +
                    else:
         | 
| 184 | 
            +
                        res['final_flag'] = res['ensemble_flag']
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                # explainability (same for all)
         | 
| 187 | 
            +
                z_df, explanations = explain_anomalies(df_fe)
         | 
| 188 | 
            +
                # attach z-scores for explain features
         | 
| 189 | 
            +
                for col in z_df.columns:
         | 
| 190 | 
            +
                    res[f'z_{col}'] = z_df[col].values
         | 
| 191 | 
            +
                res['explanation'] = explanations
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                return res
         | 
    	
        scripts/classify.py
    ADDED
    
    | @@ -0,0 +1,446 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import sys
         | 
| 2 | 
            +
            import os
         | 
| 3 | 
            +
            from pathlib import Path
         | 
| 4 | 
            +
            import pandas as pd
         | 
| 5 | 
            +
            import numpy as np
         | 
| 6 | 
            +
            from typing import Optional
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            # sklearn imports
         | 
| 9 | 
            +
            from sklearn.model_selection import train_test_split, StratifiedKFold
         | 
| 10 | 
            +
            from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
         | 
| 11 | 
            +
            from sklearn.neural_network import MLPClassifier
         | 
| 12 | 
            +
            from sklearn.pipeline import Pipeline
         | 
| 13 | 
            +
            from sklearn.compose import ColumnTransformer
         | 
| 14 | 
            +
            from sklearn.preprocessing import OneHotEncoder, StandardScaler, LabelEncoder
         | 
| 15 | 
            +
            from sklearn.impute import SimpleImputer
         | 
| 16 | 
            +
            from sklearn.metrics import classification_report
         | 
| 17 | 
            +
            import joblib
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            # Optional HF weak-labeling
         | 
| 20 | 
            +
            HF_TOKEN = os.environ.get('HF_TOKEN')
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # optional boosters
         | 
| 23 | 
            +
            try:
         | 
| 24 | 
            +
                import xgboost as xgb
         | 
| 25 | 
            +
                _has_xgb = True
         | 
| 26 | 
            +
            except Exception:
         | 
| 27 | 
            +
                _has_xgb = False
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 30 | 
            +
            def parse_and_features(df: pd.DataFrame) -> pd.DataFrame:
         | 
| 31 | 
            +
                df = df.copy()
         | 
| 32 | 
            +
                # parse datetimes
         | 
| 33 | 
            +
                for c in ['OutageDateTime','FirstRestoDateTime','LastRestoDateTime']:
         | 
| 34 | 
            +
                    if c in df.columns:
         | 
| 35 | 
            +
                        df[c+'_dt'] = pd.to_datetime(df[c], format='%d-%m-%Y %H:%M:%S', errors='coerce')
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # duration
         | 
| 38 | 
            +
                if 'OutageDateTime_dt' in df.columns and 'LastRestoDateTime_dt' in df.columns:
         | 
| 39 | 
            +
                    df['duration_min'] = (df['LastRestoDateTime_dt'] - df['OutageDateTime_dt']).dt.total_seconds() / 60.0
         | 
| 40 | 
            +
                else:
         | 
| 41 | 
            +
                    df['duration_min'] = np.nan
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                # numeric columns
         | 
| 44 | 
            +
                for col in ['Load(MW)','Capacity(kVA)','FirstStepDuration','LastStepDuration','AffectedCustomer']:
         | 
| 45 | 
            +
                    if col in df.columns:
         | 
| 46 | 
            +
                        df[col+'_num'] = pd.to_numeric(df[col], errors='coerce')
         | 
| 47 | 
            +
                    else:
         | 
| 48 | 
            +
                        df[col+'_num'] = np.nan
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                # time features
         | 
| 51 | 
            +
                if 'OutageDateTime_dt' in df.columns:
         | 
| 52 | 
            +
                    df['hour'] = df['OutageDateTime_dt'].dt.hour
         | 
| 53 | 
            +
                    df['weekday'] = df['OutageDateTime_dt'].dt.weekday
         | 
| 54 | 
            +
                else:
         | 
| 55 | 
            +
                    df['hour'] = np.nan
         | 
| 56 | 
            +
                    df['weekday'] = np.nan
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # device frequency
         | 
| 59 | 
            +
                if 'OpDeviceType' in df.columns:
         | 
| 60 | 
            +
                    freq = df['OpDeviceType'].fillna('NA').value_counts()
         | 
| 61 | 
            +
                    df['device_freq'] = df['OpDeviceType'].map(lambda x: freq.get(x,0))
         | 
| 62 | 
            +
                else:
         | 
| 63 | 
            +
                    df['device_freq'] = 0
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                # small cleanup for categorical
         | 
| 66 | 
            +
                for c in ['OpDeviceType','Owner','Weather','EventType']:
         | 
| 67 | 
            +
                    if c in df.columns:
         | 
| 68 | 
            +
                        df[c] = df[c].fillna('NA')
         | 
| 69 | 
            +
                    else:
         | 
| 70 | 
            +
                        df[c] = 'NA'
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                return df
         | 
| 73 | 
            +
             | 
| 74 | 
            +
             | 
| 75 | 
            +
            def weak_label_with_hf(text: str) -> Optional[str]:
         | 
| 76 | 
            +
                # Use HF router via OpenAI-compatible client to map free-text to a label suggestions
         | 
| 77 | 
            +
                if not HF_TOKEN or not isinstance(text, str) or not text.strip():
         | 
| 78 | 
            +
                    return None
         | 
| 79 | 
            +
                try:
         | 
| 80 | 
            +
                    from openai import OpenAI
         | 
| 81 | 
            +
                    client = OpenAI(base_url='https://router.huggingface.co/v1', api_key=HF_TOKEN)
         | 
| 82 | 
            +
                    prompt = f"ให้จัดหมวดสาเหตุของเหตุการณ์ไฟฟ้า ในคำสั้นๆ (ไทย) จากข้อความนี้:\n\n{text}\n\nตอบเป็นคำเดียวหรือวลีสั้นๆ เช่น 'สายขาด' หรือ 'บำรุงรักษา'"
         | 
| 83 | 
            +
                    completion = client.chat.completions.create(
         | 
| 84 | 
            +
                        model='meta-llama/Llama-4-Scout-17B-16E-Instruct:novita',
         | 
| 85 | 
            +
                        messages=[{"role":"user","content":[{"type":"text","text":prompt}]}],
         | 
| 86 | 
            +
                        max_tokens=40,
         | 
| 87 | 
            +
                    )
         | 
| 88 | 
            +
                    choice = completion.choices[0]
         | 
| 89 | 
            +
                    msg = getattr(choice, 'message', None) or (choice.get('message') if isinstance(choice, dict) else None)
         | 
| 90 | 
            +
                    content = None
         | 
| 91 | 
            +
                    if msg:
         | 
| 92 | 
            +
                        content = msg.get('content') if isinstance(msg, dict) else getattr(msg, 'content', None)
         | 
| 93 | 
            +
                        if isinstance(content, list) and content:
         | 
| 94 | 
            +
                            # find text
         | 
| 95 | 
            +
                            for it in content:
         | 
| 96 | 
            +
                                if isinstance(it, dict) and it.get('type') in ('output_text','text'):
         | 
| 97 | 
            +
                                    return it.get('text').strip()
         | 
| 98 | 
            +
                            return str(content[0]).strip()
         | 
| 99 | 
            +
                    # fallback
         | 
| 100 | 
            +
                    text_out = choice.get('text') if isinstance(choice, dict) else None
         | 
| 101 | 
            +
                    return text_out.strip() if text_out else None
         | 
| 102 | 
            +
                except Exception:
         | 
| 103 | 
            +
                    return None
         | 
| 104 | 
            +
             | 
| 105 | 
            +
             | 
| 106 | 
            +
            def train_classifier(df: pd.DataFrame, label_col: str = 'CauseType', test_size: float = 0.2, random_state: int = 42, min_count_to_keep: int = 2, model_type: str = 'rf', hyperparams: dict = {}):
         | 
| 107 | 
            +
                df = parse_and_features(df)
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                # optionally weak-label rows missing label
         | 
| 110 | 
            +
                if label_col not in df.columns:
         | 
| 111 | 
            +
                    df[label_col] = None
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                if df[label_col].isna().sum() > 0 and HF_TOKEN:
         | 
| 114 | 
            +
                    # attempt weak labeling for missing entries using Detail or FaultDetail
         | 
| 115 | 
            +
                    for idx, row in df[df[label_col].isna()].iterrows():
         | 
| 116 | 
            +
                        text = None
         | 
| 117 | 
            +
                        for f in ['Detail','FaultDetail','SiteDetail']:
         | 
| 118 | 
            +
                            if f in df.columns and pd.notna(row.get(f)):
         | 
| 119 | 
            +
                                text = row.get(f)
         | 
| 120 | 
            +
                                break
         | 
| 121 | 
            +
                        if text:
         | 
| 122 | 
            +
                            try:
         | 
| 123 | 
            +
                                lbl = weak_label_with_hf(text)
         | 
| 124 | 
            +
                                if lbl:
         | 
| 125 | 
            +
                                    df.at[idx, label_col] = lbl
         | 
| 126 | 
            +
                            except Exception:
         | 
| 127 | 
            +
                                pass
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                # filter rare classes and drop na
         | 
| 130 | 
            +
                if df[label_col].notna().any():
         | 
| 131 | 
            +
                    vc = df[label_col].value_counts()
         | 
| 132 | 
            +
                    rare = vc[vc < min_count_to_keep].index
         | 
| 133 | 
            +
                    if len(rare) > 0:
         | 
| 134 | 
            +
                        df[label_col] = df[label_col].apply(lambda x: 'Other' if x in rare else x)
         | 
| 135 | 
            +
                df = df.dropna(subset=[label_col])
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                # features
         | 
| 138 | 
            +
                feature_cols = ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq','OpDeviceType','Owner','Weather','EventType']
         | 
| 139 | 
            +
                X = df[feature_cols]
         | 
| 140 | 
            +
                
         | 
| 141 | 
            +
                y = df[label_col].astype(str)
         | 
| 142 | 
            +
                le = LabelEncoder()
         | 
| 143 | 
            +
                y_encoded = le.fit_transform(y)
         | 
| 144 | 
            +
                
         | 
| 145 | 
            +
                # split
         | 
| 146 | 
            +
                X_train, X_test, y_train, y_test = train_test_split(X, y_encoded, test_size=test_size, random_state=random_state, stratify=y_encoded)
         | 
| 147 | 
            +
                
         | 
| 148 | 
            +
                # model
         | 
| 149 | 
            +
                if model_type == 'rf':
         | 
| 150 | 
            +
                    clf = RandomForestClassifier(random_state=random_state, **hyperparams)
         | 
| 151 | 
            +
                elif model_type == 'gb':
         | 
| 152 | 
            +
                    clf = GradientBoostingClassifier(random_state=random_state, **hyperparams)
         | 
| 153 | 
            +
                elif model_type == 'mlp':
         | 
| 154 | 
            +
                    clf = MLPClassifier(random_state=random_state, **hyperparams)
         | 
| 155 | 
            +
                else:
         | 
| 156 | 
            +
                    raise ValueError(f"Unknown model_type: {model_type}")
         | 
| 157 | 
            +
                
         | 
| 158 | 
            +
                # preprocessor
         | 
| 159 | 
            +
                preprocessor = ColumnTransformer(
         | 
| 160 | 
            +
                    transformers=[
         | 
| 161 | 
            +
                        ('num', Pipeline([('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler())]), ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq']),
         | 
| 162 | 
            +
                        ('cat', Pipeline([('imputer', SimpleImputer(strategy='most_frequent')), ('encoder', OneHotEncoder(handle_unknown='ignore'))]), ['OpDeviceType','Owner','Weather','EventType'])
         | 
| 163 | 
            +
                    ]
         | 
| 164 | 
            +
                )
         | 
| 165 | 
            +
                
         | 
| 166 | 
            +
                pipeline = Pipeline([('preprocessor', preprocessor), ('classifier', clf)])
         | 
| 167 | 
            +
                
         | 
| 168 | 
            +
                pipeline.fit(X_train, y_train)
         | 
| 169 | 
            +
                
         | 
| 170 | 
            +
                y_pred = pipeline.predict(X_test)
         | 
| 171 | 
            +
                y_test_inv = le.inverse_transform(y_test)
         | 
| 172 | 
            +
                y_pred_inv = le.inverse_transform(y_pred)
         | 
| 173 | 
            +
                report = classification_report(y_test_inv, y_pred_inv, zero_division=0)
         | 
| 174 | 
            +
                
         | 
| 175 | 
            +
                # save model
         | 
| 176 | 
            +
                model_file = Path('outputs') / f'classifier_{model_type}_{label_col}.joblib'
         | 
| 177 | 
            +
                
         | 
| 178 | 
            +
                # predictions on train set for download
         | 
| 179 | 
            +
                y_pred_train = pipeline.predict(X)
         | 
| 180 | 
            +
                pred_df = df.copy()
         | 
| 181 | 
            +
                pred_df[f'Predicted_{label_col}'] = le.inverse_transform(y_pred_train)
         | 
| 182 | 
            +
                preds_file = Path('outputs') / f'predictions_{model_type}_{label_col}.csv'
         | 
| 183 | 
            +
                pred_df.to_csv(preds_file, index=False)
         | 
| 184 | 
            +
                
         | 
| 185 | 
            +
                return {
         | 
| 186 | 
            +
                    'report': report,
         | 
| 187 | 
            +
                    'model_file': str(model_file),
         | 
| 188 | 
            +
                    'predictions_file': str(preds_file)
         | 
| 189 | 
            +
                }
         | 
| 190 | 
            +
                df = parse_and_features(df)
         | 
| 191 | 
            +
                
         | 
| 192 | 
            +
                is_multi = len(label_cols) > 1
         | 
| 193 | 
            +
                
         | 
| 194 | 
            +
                # optionally weak-label rows missing label (only for single target)
         | 
| 195 | 
            +
                if not is_multi and label_cols[0] not in df.columns:
         | 
| 196 | 
            +
                    df[label_cols[0]] = None
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                if not is_multi and df[label_cols[0]].isna().sum() > 0 and HF_TOKEN:
         | 
| 199 | 
            +
                    # attempt weak labeling for missing entries using Detail or FaultDetail
         | 
| 200 | 
            +
                    for idx, row in df[df[label_cols[0]].isna()].iterrows():
         | 
| 201 | 
            +
                        text = None
         | 
| 202 | 
            +
                        for f in ['Detail','FaultDetail','SiteDetail']:
         | 
| 203 | 
            +
                            if f in df.columns and pd.notna(row.get(f)):
         | 
| 204 | 
            +
                                text = row.get(f)
         | 
| 205 | 
            +
                                break
         | 
| 206 | 
            +
                        if text:
         | 
| 207 | 
            +
                            try:
         | 
| 208 | 
            +
                                lbl = weak_label_with_hf(text)
         | 
| 209 | 
            +
                                if lbl:
         | 
| 210 | 
            +
                                    df.at[idx, label_cols[0]] = lbl
         | 
| 211 | 
            +
                            except Exception:
         | 
| 212 | 
            +
                                pass
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                # filter rare classes and drop na (for each label_col)
         | 
| 215 | 
            +
                for col in label_cols:
         | 
| 216 | 
            +
                    if col not in df.columns:
         | 
| 217 | 
            +
                        df[col] = None
         | 
| 218 | 
            +
                    if df[col].notna().any():
         | 
| 219 | 
            +
                        vc = df[col].value_counts()
         | 
| 220 | 
            +
                        rare = vc[vc < min_count_to_keep].index
         | 
| 221 | 
            +
                        if len(rare) > 0:
         | 
| 222 | 
            +
                            df[col] = df[col].apply(lambda x: 'Other' if x in rare else x)
         | 
| 223 | 
            +
                    df = df.dropna(subset=[col])
         | 
| 224 | 
            +
                
         | 
| 225 | 
            +
                # features
         | 
| 226 | 
            +
                feature_cols = ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq','OpDeviceType','Owner','Weather','EventType']
         | 
| 227 | 
            +
                X = df[feature_cols]
         | 
| 228 | 
            +
                
         | 
| 229 | 
            +
                # target
         | 
| 230 | 
            +
                if is_multi:
         | 
| 231 | 
            +
                    y = df[label_cols]
         | 
| 232 | 
            +
                    # encode each target
         | 
| 233 | 
            +
                    les = [LabelEncoder() for _ in label_cols]
         | 
| 234 | 
            +
                    y_encoded = np.column_stack([le.fit_transform(y[col]) for le, col in zip(les, label_cols)])
         | 
| 235 | 
            +
                else:
         | 
| 236 | 
            +
                    y = df[label_cols[0]].astype(str)
         | 
| 237 | 
            +
                    le = LabelEncoder()
         | 
| 238 | 
            +
                    y_encoded = le.fit_transform(y)
         | 
| 239 | 
            +
                    les = [le]
         | 
| 240 | 
            +
                
         | 
| 241 | 
            +
                # split
         | 
| 242 | 
            +
                X_train, X_test, y_train, y_test = train_test_split(X, y_encoded, test_size=test_size, random_state=random_state, stratify=y_encoded if not is_multi else None)
         | 
| 243 | 
            +
                
         | 
| 244 | 
            +
                # model
         | 
| 245 | 
            +
                if model_type == 'rf':
         | 
| 246 | 
            +
                    clf = RandomForestClassifier(random_state=random_state)
         | 
| 247 | 
            +
                elif model_type == 'gb':
         | 
| 248 | 
            +
                    clf = GradientBoostingClassifier(random_state=random_state)
         | 
| 249 | 
            +
                elif model_type == 'mlp':
         | 
| 250 | 
            +
                    clf = MLPClassifier(random_state=random_state, max_iter=500)
         | 
| 251 | 
            +
                else:
         | 
| 252 | 
            +
                    raise ValueError(f"Unknown model_type: {model_type}")
         | 
| 253 | 
            +
                
         | 
| 254 | 
            +
                # preprocessor
         | 
| 255 | 
            +
                preprocessor = ColumnTransformer(
         | 
| 256 | 
            +
                    transformers=[
         | 
| 257 | 
            +
                        ('num', Pipeline([('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler())]), ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq']),
         | 
| 258 | 
            +
                        ('cat', Pipeline([('imputer', SimpleImputer(strategy='most_frequent')), ('encoder', OneHotEncoder(handle_unknown='ignore'))]), ['OpDeviceType','Owner','Weather','EventType'])
         | 
| 259 | 
            +
                    ]
         | 
| 260 | 
            +
                )
         | 
| 261 | 
            +
                
         | 
| 262 | 
            +
                pipeline = Pipeline([('preprocessor', preprocessor), ('classifier', clf)])
         | 
| 263 | 
            +
                
         | 
| 264 | 
            +
                if do_gridsearch:
         | 
| 265 | 
            +
                    param_grid = {
         | 
| 266 | 
            +
                        'classifier__n_estimators': [50, 100, 200] if hasattr(clf, 'n_estimators') else [1],
         | 
| 267 | 
            +
                        'classifier__max_depth': [None, 10, 20] if hasattr(clf, 'max_depth') else [1],
         | 
| 268 | 
            +
                    }
         | 
| 269 | 
            +
                    cv = 3 if not is_multi else KFold(n_splits=3, shuffle=True, random_state=random_state)
         | 
| 270 | 
            +
                    scoring = 'accuracy' if not is_multi else None
         | 
| 271 | 
            +
                    grid = GridSearchCV(pipeline, param_grid, cv=cv, scoring=scoring, n_jobs=-1)
         | 
| 272 | 
            +
                    grid.fit(X_train, y_train)
         | 
| 273 | 
            +
                    pipeline = grid.best_estimator_
         | 
| 274 | 
            +
                
         | 
| 275 | 
            +
                pipeline.fit(X_train, y_train)
         | 
| 276 | 
            +
                
         | 
| 277 | 
            +
                # predict
         | 
| 278 | 
            +
                y_pred = pipeline.predict(X_test)
         | 
| 279 | 
            +
                
         | 
| 280 | 
            +
                # report
         | 
| 281 | 
            +
                if is_multi:
         | 
| 282 | 
            +
                    reports = []
         | 
| 283 | 
            +
                    for i, col in enumerate(label_cols):
         | 
| 284 | 
            +
                        y_test_i = y_test[:, i]
         | 
| 285 | 
            +
                        y_pred_i = y_pred[:, i]
         | 
| 286 | 
            +
                        y_test_inv = les[i].inverse_transform(y_test_i)
         | 
| 287 | 
            +
                        y_pred_inv = les[i].inverse_transform(y_pred_i.astype(int))
         | 
| 288 | 
            +
                        rep = classification_report(y_test_inv, y_pred_inv, zero_division=0)
         | 
| 289 | 
            +
                        reports.append(f"Report for {col}:\n{rep}")
         | 
| 290 | 
            +
                    report = '\n\n'.join(reports)
         | 
| 291 | 
            +
                else:
         | 
| 292 | 
            +
                    y_test_inv = les[0].inverse_transform(y_test)
         | 
| 293 | 
            +
                    y_pred_inv = les[0].inverse_transform(y_pred)
         | 
| 294 | 
            +
                    report = classification_report(y_test_inv, y_pred_inv, zero_division=0)
         | 
| 295 | 
            +
                
         | 
| 296 | 
            +
                # save model
         | 
| 297 | 
            +
                model_file = Path('outputs') / f'classifier_{model_type}_{"_".join(label_cols)}.joblib'
         | 
| 298 | 
            +
                model_file.parent.mkdir(exist_ok=True)
         | 
| 299 | 
            +
                joblib.dump({'pipeline': pipeline, 'label_encoders': les}, model_file)
         | 
| 300 | 
            +
                
         | 
| 301 | 
            +
                # predictions on train set for download
         | 
| 302 | 
            +
                y_pred_train = pipeline.predict(X)
         | 
| 303 | 
            +
                if is_multi:
         | 
| 304 | 
            +
                    pred_df = df.copy()
         | 
| 305 | 
            +
                    for i, col in enumerate(label_cols):
         | 
| 306 | 
            +
                        pred_df[f'Predicted_{col}'] = les[i].inverse_transform(y_pred_train[:, i].astype(int))
         | 
| 307 | 
            +
                else:
         | 
| 308 | 
            +
                    pred_df = df.copy()
         | 
| 309 | 
            +
                    pred_df[f'Predicted_{label_cols[0]}'] = les[0].inverse_transform(y_pred_train)
         | 
| 310 | 
            +
                
         | 
| 311 | 
            +
                preds_file = Path('outputs') / f'predictions_{model_type}_{"_".join(label_cols)}.csv'
         | 
| 312 | 
            +
                pred_df.to_csv(preds_file, index=False)
         | 
| 313 | 
            +
                
         | 
| 314 | 
            +
                return {
         | 
| 315 | 
            +
                    'report': report,
         | 
| 316 | 
            +
                    'model_file': str(model_file),
         | 
| 317 | 
            +
                    'predictions_file': str(preds_file)
         | 
| 318 | 
            +
                }
         | 
| 319 | 
            +
                df = parse_and_features(df)
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                # optionally weak-label rows missing label
         | 
| 322 | 
            +
                if label_col not in df.columns:
         | 
| 323 | 
            +
                    df[label_col] = None
         | 
| 324 | 
            +
             | 
| 325 | 
            +
                if df[label_col].isna().sum() > 0 and HF_TOKEN:
         | 
| 326 | 
            +
                    # attempt weak labeling for missing entries using Detail or FaultDetail
         | 
| 327 | 
            +
                    for idx, row in df[df[label_col].isna()].iterrows():
         | 
| 328 | 
            +
                        text = None
         | 
| 329 | 
            +
                        for f in ['Detail','FaultDetail','SiteDetail']:
         | 
| 330 | 
            +
                            if f in df.columns and pd.notna(row.get(f)):
         | 
| 331 | 
            +
                                text = row.get(f)
         | 
| 332 | 
            +
                                break
         | 
| 333 | 
            +
                        if text:
         | 
| 334 | 
            +
                            lbl = weak_label_with_hf(text)
         | 
| 335 | 
            +
                            if lbl:
         | 
| 336 | 
            +
                                df.at[idx, label_col] = lbl
         | 
| 337 | 
            +
             | 
| 338 | 
            +
                # combine rare classes into 'Other' if needed
         | 
| 339 | 
            +
                if df[label_col].notna().any():
         | 
| 340 | 
            +
                    vc = df[label_col].value_counts()
         | 
| 341 | 
            +
                    rare = vc[vc < min_count_to_keep].index.tolist()
         | 
| 342 | 
            +
                    if rare:
         | 
| 343 | 
            +
                        df[label_col] = df[label_col].apply(lambda x: 'Other' if x in rare else x)
         | 
| 344 | 
            +
             | 
| 345 | 
            +
                df = df.dropna(subset=[label_col])
         | 
| 346 | 
            +
                if df.empty:
         | 
| 347 | 
            +
                    raise ValueError('No labeled data available for training')
         | 
| 348 | 
            +
             | 
| 349 | 
            +
                # define features
         | 
| 350 | 
            +
                feature_cols = ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq','OpDeviceType','Owner','Weather','EventType']
         | 
| 351 | 
            +
                X = df[feature_cols]
         | 
| 352 | 
            +
                y = df[label_col].astype(str)
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                # encode labels to integers
         | 
| 355 | 
            +
                le = LabelEncoder()
         | 
| 356 | 
            +
                y_encoded = le.fit_transform(y)
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                # simple train/test split
         | 
| 359 | 
            +
                X_train, X_test, y_train, y_test = train_test_split(X, y_encoded, test_size=test_size, random_state=random_state, stratify=y_encoded)
         | 
| 360 | 
            +
             | 
| 361 | 
            +
                # preprocessing
         | 
| 362 | 
            +
                numeric_feats = ['duration_min','Load(MW)_num','Capacity(kVA)_num','AffectedCustomer_num','hour','weekday','device_freq']
         | 
| 363 | 
            +
                cat_feats = ['OpDeviceType','Owner','Weather','EventType']
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                numeric_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler())])
         | 
| 366 | 
            +
                # sklearn versions differ on parameter name for sparse output
         | 
| 367 | 
            +
                try:
         | 
| 368 | 
            +
                    cat_transformer = OneHotEncoder(handle_unknown='ignore', sparse_output=False)
         | 
| 369 | 
            +
                except TypeError:
         | 
| 370 | 
            +
                    cat_transformer = OneHotEncoder(handle_unknown='ignore', sparse=False)
         | 
| 371 | 
            +
             | 
| 372 | 
            +
                preprocessor = ColumnTransformer(transformers=[
         | 
| 373 | 
            +
                    ('num', numeric_transformer, numeric_feats),
         | 
| 374 | 
            +
                    ('cat', cat_transformer, cat_feats)
         | 
| 375 | 
            +
                ], remainder='drop')
         | 
| 376 | 
            +
             | 
| 377 | 
            +
                # choose classifier
         | 
| 378 | 
            +
                model_type = (model_type or 'rf').lower()
         | 
| 379 | 
            +
                if model_type == 'rf':
         | 
| 380 | 
            +
                    clf_est = RandomForestClassifier(class_weight='balanced', random_state=random_state)
         | 
| 381 | 
            +
                    clf_name = 'rf'
         | 
| 382 | 
            +
                elif model_type == 'gb':
         | 
| 383 | 
            +
                    clf_est = GradientBoostingClassifier(random_state=random_state)
         | 
| 384 | 
            +
                    clf_name = 'gb'
         | 
| 385 | 
            +
                elif model_type == 'mlp':
         | 
| 386 | 
            +
                    clf_est = MLPClassifier(hidden_layer_sizes=(100,), max_iter=300, random_state=random_state)
         | 
| 387 | 
            +
                    clf_name = 'mlp'
         | 
| 388 | 
            +
                else:
         | 
| 389 | 
            +
                    raise ValueError(f'Unknown model_type: {model_type}')
         | 
| 390 | 
            +
             | 
| 391 | 
            +
                clf = Pipeline(steps=[('pre', preprocessor), ('clf', clf_est)])
         | 
| 392 | 
            +
             | 
| 393 | 
            +
                if do_gridsearch:
         | 
| 394 | 
            +
                    if clf_name == 'rf':
         | 
| 395 | 
            +
                        param_grid = {
         | 
| 396 | 
            +
                            'clf__n_estimators': [100,200],
         | 
| 397 | 
            +
                            'clf__max_depth': [None, 10, 20],
         | 
| 398 | 
            +
                            'clf__min_samples_split': [2,5]
         | 
| 399 | 
            +
                        }
         | 
| 400 | 
            +
                    elif clf_name == 'lgb':
         | 
| 401 | 
            +
                        param_grid = {
         | 
| 402 | 
            +
                            'clf__n_estimators': [100,200],
         | 
| 403 | 
            +
                            'clf__num_leaves': [31,63]
         | 
| 404 | 
            +
                        }
         | 
| 405 | 
            +
                    elif clf_name == 'gb':
         | 
| 406 | 
            +
                        param_grid = {
         | 
| 407 | 
            +
                            'clf__n_estimators': [100,200],
         | 
| 408 | 
            +
                            'clf__max_depth': [3,6]
         | 
| 409 | 
            +
                        }
         | 
| 410 | 
            +
                    elif clf_name == 'mlp':
         | 
| 411 | 
            +
                        param_grid = {
         | 
| 412 | 
            +
                            'clf__hidden_layer_sizes': [(50,),(100,)],
         | 
| 413 | 
            +
                            'clf__alpha': [0.0001, 0.001]
         | 
| 414 | 
            +
                        }
         | 
| 415 | 
            +
                    else:
         | 
| 416 | 
            +
                        param_grid = {}
         | 
| 417 | 
            +
                    cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=random_state)
         | 
| 418 | 
            +
                    gs = GridSearchCV(clf, param_grid, cv=cv, scoring='f1_weighted', n_jobs=1)
         | 
| 419 | 
            +
                    gs.fit(X_train, y_train)
         | 
| 420 | 
            +
                    best = gs.best_estimator_
         | 
| 421 | 
            +
                    best_params = gs.best_params_
         | 
| 422 | 
            +
                    model_to_save = best
         | 
| 423 | 
            +
                else:
         | 
| 424 | 
            +
                    clf.fit(X_train, y_train)
         | 
| 425 | 
            +
                    best_params = None
         | 
| 426 | 
            +
                    model_to_save = clf
         | 
| 427 | 
            +
             | 
| 428 | 
            +
                y_pred = model_to_save.predict(X_test)
         | 
| 429 | 
            +
                unique_labels = np.unique(np.concatenate([y_test, y_pred]))
         | 
| 430 | 
            +
                target_names = [le.classes_[i] for i in unique_labels]
         | 
| 431 | 
            +
                report = classification_report(y_test, y_pred, target_names=target_names, zero_division=0)
         | 
| 432 | 
            +
                cm = confusion_matrix(y_test, y_pred)
         | 
| 433 | 
            +
             | 
| 434 | 
            +
                # save model pipeline
         | 
| 435 | 
            +
                out_dir = Path.cwd() / 'outputs'
         | 
| 436 | 
            +
                out_dir.mkdir(exist_ok=True)
         | 
| 437 | 
            +
                model_file = out_dir / f'{clf_name}_cause_pipeline.joblib'
         | 
| 438 | 
            +
                joblib.dump({'pipeline': model_to_save, 'label_encoder': le}, model_file)
         | 
| 439 | 
            +
             | 
| 440 | 
            +
                # save predictions
         | 
| 441 | 
            +
                pred_df = X_test.copy()
         | 
| 442 | 
            +
                pred_df['y_true'] = le.inverse_transform(y_test)
         | 
| 443 | 
            +
                pred_df['y_pred'] = le.inverse_transform(y_pred)
         | 
| 444 | 
            +
                pred_df.to_csv(out_dir / 'predictions_cause.csv', index=False, encoding='utf-8-sig')
         | 
| 445 | 
            +
             | 
| 446 | 
            +
                return {'model_file': str(model_file), 'report': report, 'confusion_matrix': cm, 'predictions_file': str(out_dir / 'predictions_cause.csv'), 'best_params': best_params}
         | 
    	
        scripts/data_cleansing.py
    ADDED
    
    | @@ -0,0 +1,42 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import pandas as pd
         | 
| 2 | 
            +
            import numpy as np
         | 
| 3 | 
            +
             | 
| 4 | 
            +
             | 
| 5 | 
            +
            def cleanse_data(df, remove_duplicates, missing_strategy):
         | 
| 6 | 
            +
                """
         | 
| 7 | 
            +
                Perform data cleansing on the dataframe.
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                Args:
         | 
| 10 | 
            +
                    df: pandas DataFrame
         | 
| 11 | 
            +
                    remove_duplicates: bool, whether to remove duplicate rows
         | 
| 12 | 
            +
                    missing_strategy: str, 'drop', 'impute_mean', 'impute_median', 'impute_mode'
         | 
| 13 | 
            +
                
         | 
| 14 | 
            +
                Returns:
         | 
| 15 | 
            +
                    df_clean: cleaned DataFrame
         | 
| 16 | 
            +
                    original_shape: tuple (rows, cols) before cleansing
         | 
| 17 | 
            +
                    cleaned_shape: tuple (rows, cols) after cleansing
         | 
| 18 | 
            +
                """
         | 
| 19 | 
            +
                df = df.copy()
         | 
| 20 | 
            +
                original_shape = df.shape
         | 
| 21 | 
            +
                
         | 
| 22 | 
            +
                # Remove duplicates
         | 
| 23 | 
            +
                if remove_duplicates:
         | 
| 24 | 
            +
                    df = df.drop_duplicates()
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                # Handle missing values
         | 
| 27 | 
            +
                if missing_strategy == 'drop':
         | 
| 28 | 
            +
                    df = df.dropna()
         | 
| 29 | 
            +
                elif missing_strategy in ['impute_mean', 'impute_median']:
         | 
| 30 | 
            +
                    for col in df.select_dtypes(include=[np.number]).columns:
         | 
| 31 | 
            +
                        if missing_strategy == 'impute_mean':
         | 
| 32 | 
            +
                            df[col] = df[col].fillna(df[col].mean())
         | 
| 33 | 
            +
                        elif missing_strategy == 'impute_median':
         | 
| 34 | 
            +
                            df[col] = df[col].fillna(df[col].median())
         | 
| 35 | 
            +
                elif missing_strategy == 'impute_mode':
         | 
| 36 | 
            +
                    for col in df.columns:
         | 
| 37 | 
            +
                        mode_val = df[col].mode()
         | 
| 38 | 
            +
                        if not mode_val.empty:
         | 
| 39 | 
            +
                            df[col] = df[col].fillna(mode_val[0])
         | 
| 40 | 
            +
                
         | 
| 41 | 
            +
                cleaned_shape = df.shape
         | 
| 42 | 
            +
                return df, original_shape, cleaned_shape
         | 
    	
        scripts/forecast.py
    ADDED
    
    | @@ -0,0 +1,59 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import pandas as pd
         | 
| 2 | 
            +
            import numpy as np
         | 
| 3 | 
            +
            from pathlib import Path
         | 
| 4 | 
            +
            import warnings
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            try:
         | 
| 7 | 
            +
                from prophet import Prophet
         | 
| 8 | 
            +
                PROPHET_AVAILABLE = True
         | 
| 9 | 
            +
            except Exception:
         | 
| 10 | 
            +
                PROPHET_AVAILABLE = False
         | 
| 11 | 
            +
             | 
| 12 | 
            +
             | 
| 13 | 
            +
            def prepare_timeseries(df: pd.DataFrame, date_col: str = 'OutageDateTime', metric: str = 'count') -> pd.DataFrame:
         | 
| 14 | 
            +
                # date_col is in format DD-MM-YYYY HH:MM:SS
         | 
| 15 | 
            +
                df = df.copy()
         | 
| 16 | 
            +
                df['dt'] = pd.to_datetime(df[date_col], format='%d-%m-%Y %H:%M:%S', errors='coerce')
         | 
| 17 | 
            +
                df = df.dropna(subset=['dt'])
         | 
| 18 | 
            +
                df['day'] = df['dt'].dt.floor('D')
         | 
| 19 | 
            +
                if metric == 'count':
         | 
| 20 | 
            +
                    ts = df.groupby('day').size().rename('y').reset_index()
         | 
| 21 | 
            +
                elif metric == 'downtime_minutes':
         | 
| 22 | 
            +
                    # need LastRestoDateTime
         | 
| 23 | 
            +
                    df['last_dt'] = pd.to_datetime(df.get('LastRestoDateTime'), format='%d-%m-%Y %H:%M:%S', errors='coerce')
         | 
| 24 | 
            +
                    df['duration_min'] = (df['last_dt'] - df['dt']).dt.total_seconds() / 60.0
         | 
| 25 | 
            +
                    ts = df.groupby('day')['duration_min'].sum().rename('y').reset_index()
         | 
| 26 | 
            +
                else:
         | 
| 27 | 
            +
                    raise ValueError('Unsupported metric')
         | 
| 28 | 
            +
                ts = ts.rename(columns={'day':'ds'})
         | 
| 29 | 
            +
                return ts
         | 
| 30 | 
            +
             | 
| 31 | 
            +
             | 
| 32 | 
            +
            def forecast_prophet(ts: pd.DataFrame, periods: int = 7, freq: str = 'D') -> pd.DataFrame:
         | 
| 33 | 
            +
                if not PROPHET_AVAILABLE:
         | 
| 34 | 
            +
                    raise RuntimeError('Prophet not available')
         | 
| 35 | 
            +
                m = Prophet()
         | 
| 36 | 
            +
                m.fit(ts)
         | 
| 37 | 
            +
                future = m.make_future_dataframe(periods=periods, freq=freq)
         | 
| 38 | 
            +
                fcst = m.predict(future)
         | 
| 39 | 
            +
                return fcst[['ds','yhat','yhat_lower','yhat_upper']]
         | 
| 40 | 
            +
             | 
| 41 | 
            +
             | 
| 42 | 
            +
            def forecast_naive(ts: pd.DataFrame, periods: int = 7) -> pd.DataFrame:
         | 
| 43 | 
            +
                # naive: use rolling mean of last 7 days as forecast
         | 
| 44 | 
            +
                last_mean = ts['y'].tail(7).mean() if len(ts) >= 7 else ts['y'].mean()
         | 
| 45 | 
            +
                last_date = ts['ds'].max()
         | 
| 46 | 
            +
                future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=periods, freq='D')
         | 
| 47 | 
            +
                return pd.DataFrame({'ds': future_dates, 'yhat': [last_mean]*periods, 'yhat_lower':[np.nan]*periods, 'yhat_upper':[np.nan]*periods})
         | 
| 48 | 
            +
             | 
| 49 | 
            +
             | 
| 50 | 
            +
            def run_forecast(df: pd.DataFrame, metric: str = 'count', periods: int = 7):
         | 
| 51 | 
            +
                ts = prepare_timeseries(df, metric=metric)
         | 
| 52 | 
            +
                if PROPHET_AVAILABLE and len(ts) >= 14:
         | 
| 53 | 
            +
                    try:
         | 
| 54 | 
            +
                        fcst = forecast_prophet(ts, periods=periods)
         | 
| 55 | 
            +
                        return ts, fcst
         | 
| 56 | 
            +
                    except Exception:
         | 
| 57 | 
            +
                        warnings.warn('Prophet failed, falling back to naive')
         | 
| 58 | 
            +
                fcst = forecast_naive(ts, periods=periods)
         | 
| 59 | 
            +
                return ts, fcst
         | 
    	
        scripts/label_suggestion.py
    ADDED
    
    | @@ -0,0 +1,104 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import pandas as pd
         | 
| 2 | 
            +
            from pathlib import Path
         | 
| 3 | 
            +
             | 
| 4 | 
            +
             | 
| 5 | 
            +
            def suggest_labels(df: pd.DataFrame, top_k: int = 1):
         | 
| 6 | 
            +
                """
         | 
| 7 | 
            +
                Given an event dataframe, suggest CauseType for rows with KnowUnknowCause == 'ไม่พบสาเหตุ' or missing.
         | 
| 8 | 
            +
                Returns a DataFrame with suggestions and scores.
         | 
| 9 | 
            +
                """
         | 
| 10 | 
            +
                df = df.copy()
         | 
| 11 | 
            +
                # ensure columns exist
         | 
| 12 | 
            +
                needed = ['KnowUnknowCause','CauseType','SubCauseType','OpDeviceType','FaultDeviceType','FaultDeviceCondition','Weather','Capacity(kVA)','Load(MW)','OpDeviceSysType','OpDevicePhase']
         | 
| 13 | 
            +
                for c in needed:
         | 
| 14 | 
            +
                    if c not in df.columns:
         | 
| 15 | 
            +
                        df[c] = None
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                known = df[df['KnowUnknowCause'].notna() & (df['KnowUnknowCause'].str.strip() != 'ไม่พบสาเหตุ')]
         | 
| 18 | 
            +
                unknown = df[df['KnowUnknowCause'].notna() & (df['KnowUnknowCause'].str.strip() == 'ไม่พบสาเหตุ')]
         | 
| 19 | 
            +
                unknown = pd.concat([unknown, df[df['KnowUnknowCause'].isna()]], ignore_index=False)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                if known.empty or unknown.empty:
         | 
| 22 | 
            +
                    return pd.DataFrame([])
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                for num in ['Capacity(kVA)','Load(MW)']:
         | 
| 25 | 
            +
                    known[num] = pd.to_numeric(known.get(num), errors='coerce')
         | 
| 26 | 
            +
                    unknown[num] = pd.to_numeric(unknown.get(num), errors='coerce')
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                cat_features = ['OpDeviceType','FaultDeviceType','FaultDeviceCondition','Weather','OpDeviceSysType','OpDevicePhase']
         | 
| 29 | 
            +
                num_features = ['Capacity(kVA)','Load(MW)']
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                cause_groups = {cause: g for cause, g in known.groupby('CauseType')}
         | 
| 32 | 
            +
                # compute most common SubCauseType per cause group
         | 
| 33 | 
            +
                cause_submode = {}
         | 
| 34 | 
            +
                for cause, g in cause_groups.items():
         | 
| 35 | 
            +
                    try:
         | 
| 36 | 
            +
                        # pick first mode that's non-null
         | 
| 37 | 
            +
                        modes = g['SubCauseType'].dropna()
         | 
| 38 | 
            +
                        if not modes.empty:
         | 
| 39 | 
            +
                            cause_submode[cause] = modes.mode().iloc[0]
         | 
| 40 | 
            +
                        else:
         | 
| 41 | 
            +
                            cause_submode[cause] = None
         | 
| 42 | 
            +
                    except Exception:
         | 
| 43 | 
            +
                        cause_submode[cause] = None
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                suggestions = []
         | 
| 46 | 
            +
                for idx, row in unknown.iterrows():
         | 
| 47 | 
            +
                    scores = {}
         | 
| 48 | 
            +
                    for cause, g in cause_groups.items():
         | 
| 49 | 
            +
                        cat_score = 0.0
         | 
| 50 | 
            +
                        matches = 0
         | 
| 51 | 
            +
                        for f in cat_features:
         | 
| 52 | 
            +
                            val = row.get(f)
         | 
| 53 | 
            +
                            if pd.isna(val) or val is None:
         | 
| 54 | 
            +
                                continue
         | 
| 55 | 
            +
                            same = (g[f] == val).sum()
         | 
| 56 | 
            +
                            frac = same / max(1, len(g))
         | 
| 57 | 
            +
                            cat_score += frac
         | 
| 58 | 
            +
                            matches += 1
         | 
| 59 | 
            +
                        cat_score = cat_score / matches if matches>0 else 0.0
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                        num_score = 0.0
         | 
| 62 | 
            +
                        ncount = 0
         | 
| 63 | 
            +
                        for nf in num_features:
         | 
| 64 | 
            +
                            rv = row.get(nf)
         | 
| 65 | 
            +
                            if pd.isna(rv) or rv is None:
         | 
| 66 | 
            +
                                continue
         | 
| 67 | 
            +
                            median = g[nf].median()
         | 
| 68 | 
            +
                            if pd.isna(median):
         | 
| 69 | 
            +
                                continue
         | 
| 70 | 
            +
                            scale = abs(median) if abs(median) > 0 else 1.0
         | 
| 71 | 
            +
                            num_score += 1.0 / (1.0 + abs(rv - median) / scale)
         | 
| 72 | 
            +
                            ncount += 1
         | 
| 73 | 
            +
                        num_score = num_score / ncount if ncount>0 else 0.0
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        combined = 0.7 * cat_score + 0.3 * num_score
         | 
| 76 | 
            +
                        scores[cause] = combined
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    sorted_scores = sorted(scores.items(), key=lambda x: x[1], reverse=True)
         | 
| 79 | 
            +
                    top = sorted_scores[:int(top_k)]
         | 
| 80 | 
            +
                    suggestion_text = '; '.join([f"{c}: {s:.3f}" for c,s in top])
         | 
| 81 | 
            +
                    suggested_cause = top[0][0] if top else None
         | 
| 82 | 
            +
                    suggested_subcause = cause_submode.get(suggested_cause) if suggested_cause is not None else None
         | 
| 83 | 
            +
                    suggestions.append({
         | 
| 84 | 
            +
                        'Number': row.get('Number'),
         | 
| 85 | 
            +
                        'EventNumber': row.get('EventNumber'),
         | 
| 86 | 
            +
                        'OutageDateTime': row.get('OutageDateTime'),
         | 
| 87 | 
            +
                        'KnowUnknowCause': row.get('KnowUnknowCause'),
         | 
| 88 | 
            +
                        'Orig_CauseType': row.get('CauseType'),
         | 
| 89 | 
            +
                        'Orig_SubCauseType': row.get('SubCauseType'),
         | 
| 90 | 
            +
                        'SuggestedCause': suggested_cause,
         | 
| 91 | 
            +
                        'SuggestedSubCauseType': suggested_subcause,
         | 
| 92 | 
            +
                        'Scores': suggestion_text
         | 
| 93 | 
            +
                    })
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                return pd.DataFrame(suggestions)
         | 
| 96 | 
            +
             | 
| 97 | 
            +
             | 
| 98 | 
            +
            def suggest_labels_to_file(df: pd.DataFrame, out_path: str = None, top_k: int = 1):
         | 
| 99 | 
            +
                out_df = suggest_labels(df, top_k=top_k)
         | 
| 100 | 
            +
                if out_path:
         | 
| 101 | 
            +
                    p = Path(out_path)
         | 
| 102 | 
            +
                    p.parent.mkdir(parents=True, exist_ok=True)
         | 
| 103 | 
            +
                    out_df.to_csv(p, index=False, encoding='utf-8-sig')
         | 
| 104 | 
            +
                return out_df
         | 
    	
        scripts/summarize.py
    ADDED
    
    | @@ -0,0 +1,73 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import pandas as pd
         | 
| 3 | 
            +
            from typing import List, Dict
         | 
| 4 | 
            +
            from pathlib import Path
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # Prefer HF router via OpenAI-compatible client. Use env `HF_TOKEN`.
         | 
| 7 | 
            +
            # HF_TOKEN loaded lazily to allow dotenv loading after import
         | 
| 8 | 
            +
            def get_hf_token():
         | 
| 9 | 
            +
                return os.environ.get('HF_TOKEN')
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            def rule_summary(row: pd.Series) -> str:
         | 
| 12 | 
            +
                parts = []
         | 
| 13 | 
            +
                if pd.notna(row.get('EventType')):
         | 
| 14 | 
            +
                    parts.append(f"ประเภท: {row['EventType']}")
         | 
| 15 | 
            +
                if pd.notna(row.get('CauseType')):
         | 
| 16 | 
            +
                    parts.append(f"สาเหตุ: {row['CauseType']}")
         | 
| 17 | 
            +
                if pd.notna(row.get('OutageDateTime')):
         | 
| 18 | 
            +
                    parts.append(f"เวลาเริ่ม: {row['OutageDateTime']}")
         | 
| 19 | 
            +
                if pd.notna(row.get('AffectedCustomer')):
         | 
| 20 | 
            +
                    parts.append(f"ลูกค้าได้รับผลกระทบ: {row['AffectedCustomer']}")
         | 
| 21 | 
            +
                if pd.notna(row.get('Load(MW)')):
         | 
| 22 | 
            +
                    parts.append(f"โหลด: {row['Load(MW)']}")
         | 
| 23 | 
            +
                return ' | '.join(parts) if parts else ''
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
            def openai_summary(text: str, verbosity: str = 'brief', model: str = 'meta-llama/Llama-3.1-8B-Instruct:novita') -> str:
         | 
| 27 | 
            +
                HF_TOKEN = get_hf_token()
         | 
| 28 | 
            +
                if not HF_TOKEN:
         | 
| 29 | 
            +
                    return None
         | 
| 30 | 
            +
                try:
         | 
| 31 | 
            +
                    # Import here to avoid requiring OpenAI client unless HF_TOKEN set
         | 
| 32 | 
            +
                    from openai import OpenAI
         | 
| 33 | 
            +
                    client = OpenAI(base_url="https://router.huggingface.co/v1", api_key=HF_TOKEN)
         | 
| 34 | 
            +
                    if verbosity == 'analyze':
         | 
| 35 | 
            +
                        instruction = 'วิเคราะห์สาเหตุไฟฟ้าจากข้อมูลนี้ สรุปไม่เกิน 3-4 บรรทัด (ไทย) ระบุสาเหตุทางเทคนิค ผลกระทบต่อลูกค้าและระบบ และช่วงเวลา:'
         | 
| 36 | 
            +
                    elif verbosity == 'recommend':
         | 
| 37 | 
            +
                        instruction = 'วิเคราะห์สาเหตุไฟฟ้าจากข้อมูลนี้ พร้อมแนะนำการแก้ไข สรุปไม่เกิน 3-4 บรรทัด (ไทย) ระบุสาเหตุทางเทคนิค ผลกระทบต่อลูกค้าและระบบ ช่วงเวลาและข้อเสนอแนะในการป้องกัน:'
         | 
| 38 | 
            +
                    prompt = f"{instruction}\n\n{text}\n\nสรุป:" 
         | 
| 39 | 
            +
                    completion = client.chat.completions.create(
         | 
| 40 | 
            +
                        model=model,
         | 
| 41 | 
            +
                        messages=[{"role": "user", "content": prompt}],
         | 
| 42 | 
            +
                        max_tokens=1000,
         | 
| 43 | 
            +
                    )
         | 
| 44 | 
            +
                    # Extract text from response
         | 
| 45 | 
            +
                    choice = completion.choices[0]
         | 
| 46 | 
            +
                    msg = choice.message
         | 
| 47 | 
            +
                    content = msg.content
         | 
| 48 | 
            +
                    return content.strip() if content else None
         | 
| 49 | 
            +
                except Exception:
         | 
| 50 | 
            +
                    return None
         | 
| 51 | 
            +
             | 
| 52 | 
            +
             | 
| 53 | 
            +
            def summarize_events(df: pd.DataFrame, use_hf: bool = False, verbosity: str = 'brief', model: str = 'meta-llama/Llama-3.1-8B-Instruct:novita') -> List[Dict]:
         | 
| 54 | 
            +
                rows = []
         | 
| 55 | 
            +
                for _, r in df.iterrows():
         | 
| 56 | 
            +
                    text_fields = []
         | 
| 57 | 
            +
                    for col in df.columns:
         | 
| 58 | 
            +
                        if pd.notna(r.get(col)) and str(r.get(col)).strip():
         | 
| 59 | 
            +
                            text_fields.append(f"{col}: {r[col]}")
         | 
| 60 | 
            +
                    long_text = '\n'.join(text_fields)
         | 
| 61 | 
            +
                    print(f"Debug: EventNumber={r.get('EventNumber','')}, long_text='{long_text}'")
         | 
| 62 | 
            +
                    summary = None
         | 
| 63 | 
            +
                    if use_hf and get_hf_token() and long_text:
         | 
| 64 | 
            +
                        # prefer HF router
         | 
| 65 | 
            +
                        summary = openai_summary(long_text, verbosity=verbosity, model=model)
         | 
| 66 | 
            +
                    if not summary:
         | 
| 67 | 
            +
                        summary = rule_summary(r)
         | 
| 68 | 
            +
                    rows.append({
         | 
| 69 | 
            +
                        'EventNumber': r.get('EventNumber',''),
         | 
| 70 | 
            +
                        'OutageDateTime': r.get('OutageDateTime',''),
         | 
| 71 | 
            +
                        'Summary': summary,
         | 
| 72 | 
            +
                    })
         | 
| 73 | 
            +
                return rows
         | 
