نویسنده (ها): رویز ریورا
در ابتدا منتشر شده در به سمت هوش مصنوعیبشر


این را تصویر کنید: شما یک دانشمند داده ای هستید که با داده های آتش سوزی کار می کنید ، و تمام آنچه شما دارید سوابق آتش سوزی اساسی است – مختصات موقعیت مکانی ، جدول زمانی و شاید یک شناسه آتش منحصر به فرد. در حالی که این اطلاعات به شما می گوید کجا وت کی آتش سوزی رخ داد ، به شما نمی گوید چرا این کار را شروع کرد یا گسترش داد.
شرایط آب و هوایی نقش مهمی در رفتار آتش سوزی دارد. دما ، سرعت باد ، رطوبت و رطوبت خاک می تواند به معنای تفاوت بین آتش سوزی چمن کوچک و یک آتش سوزی ویرانگر باشد. اما جمع آوری دستی داده های آب و هوایی تاریخی برای صدها یا هزاران مکان آتش نشانی؟ این به نظر می رسد مانند کابوس.
اینجاست که قدرت Python و Google Earth Engine به نجات می رسد! با داشتن زمینه اضافی که به کد ما ساخته شده است ، ما قادر به ساختن مدل خطرناک تر آتش سوزی با کمک یادگیری ماشین برای ترکیب الگوهای آب و هوایی تاریخی در کنار داده های مکان و پوشش گیاهی ، به طور بالقوه مناطق پرخطر را قبل از شروع فصل آتش سوزی شناسایی می کند.
نتایج این کار بسیار مهم است زیرا محدودیت های آزمایشگاه ها و دفاتر را که در مورد این چالش ها فکر می کنند ، گسترش می دهد. به عنوان مثال ، از طیف گسترده ای از بخش هایی که می توانیم با این مهندسی تأثیر بگذاریم مجموعه داده، موردی که شاید در مورد آن فکر نکرده باشید صنعت بیمه است. شرکت های بیمه می توانند از این غنی شده استفاده کنند مجموعه داده برای توسعه حق بیمه خطر آتش سوزی دقیق تر با تجزیه و تحلیل چگونگی شرایط آب و هوایی خاص (مانند رطوبت کم همراه با وزش باد) با شدت آتش سوزی و آسیب های خاصیت ارتباط دارد و منجر به مدل های دقیق تر و قیمت گذاری عادلانه تر می شود. ما همچنین می توانیم با کمک به آنها در توسعه سیستم های هشدار اولیه موثرتر از طریق شناسایی شرایط آب و هوایی که از نظر تاریخی پیش از آتش سوزی های بزرگ بودند ، بر آژانس های مدیریت اضطراری تأثیر بگذاریم ، بنابراین آنها را قادر می سازد هشدارهای هدفمند را صادر کنند و منابع را به صورت پیشگیرانه مستقر کنند تا نه تنها املاک بلکه از همه مهمتر زندگی کنند.
در این آموزش ، ابزاری را ایجاد خواهیم کرد که به طور خودکار مجموعه داده های آتش سوزی را با اطلاعات جامع آب و هوا غنی سازی می کند ، امکانات جدیدی را برای ارزیابی ریسک آتش ، مدل سازی بیمه و برنامه های تحقیقاتی باز می کند. در پایان آن ، یک اسکریپت پایتون خواهید داشت که می تواند موارد زیر را انجام دهد:
- داده های مکان را بگیرید (مختصات + Timestamps)
- به طور خودکار داده های هواشناسی تاریخی از مجموعه داده ERA5 Google Earth Engine
- مجموعه داده های بزرگ را با استفاده از پردازش دسته ای پردازش کنید
- کنترل چندین قالب پرونده (CSV ، Excel ، JSON ، SQLITE)
- صادرات مجموعه داده های غنی شده آماده برای تجزیه و تحلیل
داده های غنی شده شامل دما ، سرعت/جهت باد ، سطح رطوبت و دمای خاک – تمام زمینه محیطی مورد نیاز شما برای تجزیه و تحلیل آتش سوزی معنی دار است. شما آماده هستید تا با داده ها تأثیر زیادی بگذارد؟ درست پس از آن بیایید شروع کنیم
پیش نیازهای
قبل از غواصی ، مطمئن شوید که:
- پایتون 3.8+ نصب شده است
- یک پروژه Google Cloud با API Earth Engine فعال شده است
- آشنایی اساسی با پاندا و دستکاری داده ها
1. نصب وابستگی ها
ابتدا بیایید بسته های مورد نیاز را با ذخیره آنها و نسخه های مورد نظر آنها در پرونده ای که عنوان خواهیم کرد ، نصب کنیم requirements.txt
:
earthengine-api==0.1.406
geemap==0.32.1 #Backup version: 0.20.4
pandas>=1.3.0
python-dotenv>=0.19.0
requests>=2.25.0
سپس دستور زیر را در ترمینال اجرا کنید که می تواند اسکریپت های پایتون مانند Bash یا Anaconda را اجرا کند:
!pip install -r requirements.txt
2. پیکربندی پروژه
و اگر قبلاً .env
پرونده در مخزن خود ، با استفاده از دستورات زیر یکی را ایجاد کنید:
touch .env
start .env
اگر به ایجاد یک پروژه Google Earth Engine نیاز دارید ، برای شما خوش شانس است که من منتشر کرده ام آموزش دقیقاً در نحوه انجام این کار در صورت لزوم حتماً آن را بررسی کنید!
این رویکرد اطلاعات حساس را از کد شما خارج می کند-مناسب برای به اشتراک گذاری یا پروژه های منبع باز. هنگامی که نام پروژه Google Earth Engine را در جای خود دارید ، ویرایش کنید .env
پرونده پروژه Google Earth Engine خود را در آن اضافه کنید:
PROJECT_NAME="insert-your-project-name"
3. اعتبار خود را ایمن کنید
علاوه بر این ، اضافه کردن a بسیار مهم است .gitignore
پرونده به مخزن ما با استفاده از دستورات زیر که قبلاً در صورتی که قبلاً آن را نداریم دیدیم:
touch .gitignore
start .gitignore
در .gitignore
پرونده به عنوان یک نگهبان امنیتی برای مخزن شما عمل می کند و از ردیابی ، بارگذاری و نمایش اطلاعات حساس هنگام متعهد شدن کد به سیستم عامل های کنترل نسخه مانند GitHub جلوگیری می کند. افزودن پرونده هایی مانند .env
به .gitignore
بسیار مهم است زیرا این پرونده ها حاوی اطلاعات حساس مانند نام پروژه Google Cloud ، کلیدهای API ، رمزهای عبور و سایر اسرار پیکربندی شما هستند که هرگز نباید به طور عمومی قابل مشاهده باشند. بدون مناسب .gitignore
حفاظت ، شما می توانید به طور تصادفی اعتبار پروژه خود را در معرض هر کسی که مخزن شما را مشاهده می کند ، به طور بالقوه منجر به دسترسی غیرمجاز به منابع موتور Google Earth یا هزینه های صورتحساب غیر منتظره شود.
در .gitignore
پرونده تضمین می کند که فقط کد شما در حالی که پیکربندی شخصی و اعتبار خود را با خیال راحت در دستگاه محلی خود نگه می دارد ، به صورت عمومی به اشتراک می گذارد. اگر کنجکاو هستید که چه .gitignore
به نظر می رسد پرونده یا چگونه باید ساختار یافته باشد ، احساس راحتی کنید الگو را بررسی کنید من برای این پروژه استفاده کرده ام.
4. نیازهای داده را وارد کنید
آخرین پیش نیاز ما هنگام تغذیه داده ها به اسکریپت ما به آن نیاز داریم این است که انتظار دارد داده های آتش سوزی حاوی برخی از نسخه های این چهار ستون اساسی باشد:


توجه داشته باشید که قالب تاریخ انعطاف پذیر است زیرا می تواند هر دو را اداره کند YYYYMMDD
(فقط تاریخ) و YYYYMMDDHHMMSS
(تاریخ و زمان) قالب ها. برای اجرای اسکریپت ما ، ما به مسیر پرونده یا پیوندی که به مجموعه داده ای که برای پردازش برنامه ریزی می کنید ، نیاز داریم.
درک اجزای اصلی
اکنون که ما زمینه را برای اجرای موفقیت آمیز (و با خیال راحت) این آموزش قرار داده ایم ، بیایید قطعه کد Python را به صورت قطعه انجام دهیم ، بنابراین می دانیم که چگونه این داده های هواشناسی تاریخی را استخراج می کنیم:
1. برنامه تبدیل تاریخ
یک چالش با مجموعه داده های آتش سوزی قالب های تاریخ متناقض است. با کد زیر ، بیایید یک عملکرد مبدل تاریخ قوی ایجاد کنیم که می تواند با ظرافت قالب های مختلف تاریخ را کنترل کند و مقادیر گمشده ضروری برای پردازش داده های دنیای واقعی:
import ee
import geemap
import logging
import math
import random
import requests
import os
import sqlite3
import time
import datetime as dt
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
from dotenv import load_dotenv# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def convert_float_to_datetime(series):
"""
Converts a pandas Series of float-based date values to datetime.
Handles:
- 8-digit formats (YYYYMMDD)
- 14-digit formats (YYYYMMDDHHMMSS)
- Invalid lengths become NaT
"""
# Initialize output series with NaT (same index/dtype as input)
datetime_series = pd.Series(index=series.index,
data=series, # data=pd.NaT,
dtype='datetime64[ns]')# Process non-null values
non_null = series.dropna()
if non_null.empty:
return datetime_series
try:
# Convert to integer then string (avoids scientific notation)
str_dates = non_null.astype('int64').astype(str)
# Identify valid date lengths
mask_8 = str_dates.str.len() == 8 # Date only
mask_14 = str_dates.str.len() == 14 # Date + time
# Parse valid formats
parsed_dates = pd.concat([
pd.to_datetime(str_dates[mask_8], format='%Y%m%d', errors='coerce'),
pd.to_datetime(str_dates[mask_14], format='%Y%m%d%H%M%S', errors='coerce')
]).sort_index() # Maintain original order
# Update result series with valid dates
datetime_series.update(parsed_dates)
except Exception as e:
print(f"Conversion error: {str(e)}")
return datetime_series
ما همچنین ایجاد کرده ایم create_dataframe()
عملکرد به عنوان یک لودر داده جهانی که از نظر هوشمندانه از چندین مسیر فایل محلی و URL های از راه دور استفاده می کند ، از نظر هوشمندانه از قالب های مختلف پرونده (CSV ، Excel ، JSON ، SQLITE) استفاده می کند ، و این باعث می شود بدون توجه به نحوه ذخیره آنها ، برای بارگیری مجموعه داده های آتش سوزی بسیار کاربر پسند باشد. این نوع پرونده را بر اساس پسوند پرونده تشخیص می دهد و روش مناسب خواندن پاندا را اعمال می کند ، در حالی که می تواند از طریق فرآیند بارگیری داده ها ، کاربران را راهنمایی کند.
def create_dataframe(hardcoded_path=None, sheet_name=None, db_name=None, table_name=None):
"""
Create a Pandas DataFrame from a file path or a link.Parameters:
- hardcoded_path (str, optional): The file path or link to be used. If None, the user will be prompted to enter it.
- sheet_name (str, optional): The sheet name for Excel files or table name for SQL databases.
- db_name (str, optional): The database name for SQL databases.
- table_name (str, optional): The table name for SQL databases.
"""
if hardcoded_path is None:
filepath_or_link = input("/n Please enter the file path or link for the data source: ")
else:
filepath_or_link = hardcoded_pathtry:
# Handle web URL
if filepath_or_link.startswith(('http://', 'https://')):
if filepath_or_link.endswith('.csv'):
df = pd.read_csv(filepath_or_link)
elif filepath_or_link.endswith(('.xls', '.xlsx')):
df = pd.read_excel(filepath_or_link, sheet_name=sheet_name)
elif filepath_or_link.endswith('.json'):
df = pd.read_json(filepath_or_link)
elif filepath_or_link.endswith('.db'):
response = requests.get(filepath_or_link)
db_name = input("\n Please enter the DATABASE NAME ONLY (do not include the .db extension): ")
table_name = input(f"\n Please enter the specific TABLE NAME you wish to access in the {db_name} database: ")
with open(db_name, "wb") as f:
f.write(response.content)
conn = sqlite3.connect(db_name)
query = f"SELECT * FROM {table_name}" if table_name else "SELECT * FROM sqlite_master WHERE type='table';"
df = pd.read_sql_query(query, conn)
conn.close()
else:
raise ValueError("Unsupported file format from the URL.")
else:
# Handle local file path
filepath_or_link = os.path.expanduser(filepath_or_link)
if not os.path.exists(filepath_or_link):
raise FileNotFoundError(f"The file {filepath_or_link} does not exist.")
if filepath_or_link.endswith('.csv'):
df = pd.read_csv(filepath_or_link)
elif filepath_or_link.endswith(('.xls', '.xlsx')):
df = pd.read_excel(filepath_or_link, sheet_name=sheet_name)
elif filepath_or_link.endswith('.json'):
df = pd.read_json(filepath_or_link)
elif filepath_or_link.endswith('.db'):
conn = sqlite3.connect(filepath_or_link)
query = f"SELECT * FROM {table_name}" if table_name else "SELECT * FROM sqlite_master WHERE type='table';"
df = pd.read_sql_query(query, conn)
conn.close()
else:
raise ValueError("Unsupported file format.")
print("\n ✅ DataFrame created successfully:")
return df
except Exception as e:
print(f"\n 🙄 An error occurred: {e}")
return None
2. توابع یاور
با استفاده از عملکردهای سودمند ما ، بیایید در مورد دسترسی به API موتور Google Earth صحبت کنیم! قلب ابزار ما است get_weather_data()
عملکردی که ما برای پرس و جو از موتور زمین Google برای داده های آب و هوا نوشتیم. هدف از این عملکرد ، رسیدگی به فرآیند پیچیده پرس و جو از داده های ماهواره ای ، تبدیل واحدها و محاسبه معیارهای مشتق شده مانند سرعت باد از بردارهای مؤلفه است.
و در داخل get_weather_data()
هستند توابع یاور مثل sample_point_data()
عملکردی که پیچیدگی فنی در استخراج داده های آب و هوا از Google Earth Engine را در مختصات خاص ، از جمله رسیدگی به خطا در هنگام دسترسی به داده های ماهواره ای در یک مکان ، کنترل می کند. این اجازه می دهد پیچیدگی های API موتور زمین ، اجازه می دهد get_weather_data()
برای تمرکز بر منطق پردازش داده ها به جای جزئیات مدیریت API.
def sample_point_data(weather_data, point, lat, lon, date_val):
"""
Sample Earth Engine data at a specific point.Args:
weather_data: Earth Engine Image with weather variables
point: Earth Engine Geometry point
lat: Latitude value for logging
lon: Longitude value for logging
date_val: Date value for logging
Returns:
Dictionary of sampled data or None if no data available
"""
sample_result = weather_data.sample(point, 30).first()# Check if sample_result is null
if sample_result is None or ee.Algorithms.IsEqual(sample_result, None).getInfo():
logger.warning(f"No data at point ({lat}, {lon}) for date {date_val}")
return None
# Convert to dictionary
return sample_result.toDictionary().getInfo()
به نظر من ، جادو با این روند ماست retry_with_backoff()
عملکرد دکوراتور برای پشتیبانی از sample_point_data()
عملکرد را با استفاده مجدد از تماس های API شکست خورده به Google Earth Engine انجام دهید. با این حال ، آنچه در مورد این عملکرد جالب است این است که باعث افزایش تأخیر بین تلاش ها می شود و باعث می شود روند استخراج داده های آب و هوا در برابر مسائل شبکه موقت یا زمان های API قوی تر شود. همچنین این کار را پشتوانه نمایی (دو برابر شدن زمان انتظار بعد از هر شکست) انجام می دهد و باعث می شود تا از چندین فرآیند جلوگیری کند که API را به طور همزمان هنگام تلاش مجدد از فرآیندهای متعدد جلوگیری کند. این عملکرد برای رسیدگی به بی ثباتی ذاتی تماس های API از راه دور بسیار مهم است ، و اطمینان حاصل می کند که سکسکه موقت کل فرآیند غنی سازی داده های آب و هوا را هنگام پردازش مجموعه داده های بزرگ آتش سوزی از بین نمی برد.
# Apply the retry decorator to the sampling function
sample_point_data_with_retry = retry_with_backoff()(sample_point_data)
یکی دیگر از عملکردهای مهم یاور این است که wind_direction_to_text()
که جهت باد محاسبه شده را از درجه ها (مانند 245.8 درجه) به جهت های کاردینال قابل خواندن انسان (مانند “جنوب غربی”) تبدیل می کند و باعث می شود مجموعه داده های خروجی برای تحلیلگران و محققان قابل تفسیر باشد.
def wind_direction_to_text(wind_dir_deg):
"""
Convert wind direction in degrees to 8-point cardinal direction.Args:
wind_dir_deg (float): Wind direction in degrees (0-360)Returns:
str: Cardinal direction as text (N, NE, E, SE, S, SW, W, NW)
"""
# Define direction ranges and corresponding text
directions = [
(337.5, 360, "North"),
(0, 22.5, "North"),
(22.5, 67.5, "Northeast"),
(67.5, 112.5, "East"),
(112.5, 157.5, "Southeast"),
(157.5, 202.5, "South"),
(202.5, 247.5, "Southwest"),
(247.5, 292.5, "West"),
(292.5, 337.5, "Northwest")
]# Normalize the degree to be between 0 and 360
wind_dir_deg = wind_dir_deg % 360# Find the matching direction
(start and end == 360):
for start, end, direction in directions:
if (start or
return direction# This should never happen if the ranges are correct
return "Unknown"
با هم ، این توابع نگرانی های جداگانه ای را در جایی که پیچیدگی استخراج داده ها را کنترل می کند ، جدا می کند در حالی که دومی قابلیت استفاده داده را افزایش می دهد – اجازه می دهد get_weather_data()
برای ارکستر کردن روند کلی غنی سازی آب و هوا به صورت پاک:
def get_weather_data(row, id_col):
"""
Extract weather data from Google Earth Engine for a specific location and time.Args:
row: DataFrame row containing 'ignition_datetime', 'LATITUDE', and 'LONGITUDE'
Returns:
dict: Weather data or NaN values if data cannot be retrieved
"""
# Validate input data
date_val = row.get('ignition_datetime')
lat = row.get('LATITUDE')
lon = row.get('LONGITUDE')
fire_label = row.get(id_col)# Initialize default return values
default_values = {
'temperature_c': np.nan,
'wind_speed_ms': np.nan,
'wind_direction_deg': np.nan,
'wind_direction': 'No data returned',
'humidity_dewpoint_temperature_2m': np.nan,
'soil_temperature_level_1': np.nan,
'fire_label': fire_label,
'ignition_datetime': date_val
}
try:
# Check if we have all required values
if date_val is None or pd.isna(date_val) or not isinstance(date_val, datetime):
logger.warning(f"Fire label {fire_label} has an invalid ignition_datetime: {date_val}")
return default_values
if lat is None or pd.isna(lat) or lon is None or pd.isna(lon):
logger.warning(f"Fire label {fire_label} has an invalid coordinates: lat={lat}, lon={lon}")
return default_values
# Convert datetime to Earth Engine format
date = ee.Date(date_val)
# Create point geometry
point = ee.Geometry.Point([lon, lat])
# Get ERA5 reanalysis data
# era5 = ee.ImageCollection('ECMWF/ERA5/HOURLY')
era5 = ee.ImageCollection('ECMWF/ERA5_LAND/HOURLY')
# Filter to the date (add buffer to ensure we get data)
start_date = date.advance(-1, 'hour')
end_date = date.advance(2, 'hour')
era5_filtered = era5.filterDate(start_date, end_date)
# Check if we have any images
if era5_filtered.size().getInfo() == 0:
logger.warning(f"No ERA5 data found for time range around {date_val} for the {fire_label} fire label")
# return None
return default_values
# Get the image closest to our target time
era5_list = era5_filtered.toList(era5_filtered.size())
era5_img = ee.Image(era5_list.get(0)) # Get first image
# Extract weather variables at the point (using resample for faster computation)
weather_data = era5_img.select(
['temperature_2m', 'u_component_of_wind_10m',
'v_component_of_wind_10m', 'dewpoint_temperature_2m', 'soil_temperature_level_1']).resample("bilinear")
# Sample the point with error handling and retry
try:
data = sample_point_data_with_retry(weather_data, point, lat, lon, date_val)
# Check if data is empty
if not data:
logger.warning(f"Empty data returned for ({lat}, {lon}) at {date_val} for the {fire_label} fire label")
return default_values
# Calculate wind speed and direction from u,v components
u = data.get('u_component_of_wind_10m', 0)
v = data.get('v_component_of_wind_10m', 0)
wind_speed = (u**2 + v**2)**0.5
# Avoid division by zero or undefined math
if u == 0 and v == 0:
wind_dir = 0 # No wind
else:
wind_dir = (270 - (180/3.14159) * math.atan2(v, u)) % 360
# Convert temperature from K to C (handle None values)
temp_k = data.get('temperature_2m')
temp_c = temp_k - 273.15 if temp_k is not None else np.nan
return {
'temperature_c': temp_c,
'wind_speed_ms': wind_speed,
'wind_direction_deg': wind_dir,
'wind_direction': wind_direction_to_text(wind_dir),
'humidity_dewpoint_temperature_2m': data.get('dewpoint_temperature_2m'),
'soil_temperature_level_1': data.get('soil_temperature_level_1'),
'fire_label': fire_label,
'ignition_datetime': date_val
}
except ee.EEException as e:
logger.error(f"Earth Engine sampling error for ({lat}, {lon}) at {date_val}: {str(e)}")
return default_values
except Exception as e:
logger.error(f"Error processing row: {str(e)}")
# For debugging in development
# import traceback
# logger.error(traceback.format_exc())
return default_values
3. استخراج داده ها
اکنون که درک کردیم که چگونه داده ها از موتور Google Earth استخراج می شود ، اکنون می خواهیم نگاهی به عملکردی که این کل فرآیند را نشان می دهد ، نگاهی بیندازیم. در process_dataframe()
عملکرد این کارگاه کاری است که مجموعه داده های بزرگ آتش سوزی را به دسته های قابل کنترل (100 سوابق پیش فرض) می شکند تا ضمن ارائه به روزرسانی های پیشرفت در زمان واقعی ، از محدودیت های API Google Earth Engine جلوگیری شود. این شامل رسیدگی به خطای هوشمند است که به پردازش اجازه می دهد حتی اگر دسته های انفرادی شکست بخورد ، ادامه یابد و به طور خودکار نتایج هر دسته را ذخیره می کند تا در صورت قطع روند از دست دادن داده ها جلوگیری شود. این عملکرد همچنین تأخیرهای اجباری بین دسته ها را برای احترام به محدودیت های نرخ API ، اطمینان از استخراج داده های صاف و قابل اعتماد در آب و هوا شامل می شود.
def process_dataframe(df, batch_size=100, batch_delay=3, id_col=None):
"""
Process the dataframe in batches to avoid Earth Engine quota issues.Args:
df: DataFrame with wildfire data
batch_size: Number of rows to process in each batch
batch_delay: Delay in seconds between processing batches
Returns:
DataFrame with added weather data
"""
df = df[df["ignition_datetime"].notna()].sort_values("ignition_datetime")
results = []
total_batches = (len(df) + batch_size - 1) // batch_size
# Process in batches
for i in range(0, len(df), batch_size):
batch = df.iloc[i:i+batch_size]
batch_num = i//batch_size + 1
# Clear progress reporting
print(f"\n Processing batch {batch_num} of {total_batches} (rows {i} to {min(i+batch_size-1, len(df)-1)})")
logger.info(f"\n Processing batch {batch_num} of {total_batches} (rows {i} to {min(i+batch_size-1, len(df)-1)})")
# Apply to each row in this batch
batch_results = batch.apply(get_weather_data, axis=1, result_type='expand', args=(id_col,))
### ADDITIONAL CHECK ###
# Check if 'temp_c' key exists in the dictionary and is not empty # or not(bool(batch_results['temperature_c']))
if 'temperature_c' not in batch_results or (len(batch_results['temperature_c'].value_counts()) == 0):
print(f"Skipping batch {batch_num} of {total_batches} - no temperature data available \n\n")
continue # Skip to the next iteration of the loop
else:
results.append(batch_results)
# Add progress information
print(f"\n Completed batch {batch_num}/{total_batches} ({batch_num/total_batches*100:.1f}%) \n")
logger.info(f"Completed batch {batch_num}/{total_batches} ({batch_num/total_batches*100:.1f}%)")
# Saving each batch to ensure we don't waste computation:
download_name = f"weather_data_batch_{batch_num}_of_{total_batches}.csv"
save_results_to_downloads(batch_results, filename=download_name)
# Add a delay between batches to reduce pressure on the API
if batch_num print(f"\n Pausing for {batch_delay} second(s) before next batch... \n\n")
logger.info(f"Pausing for {batch_delay} second(s) before next batch...")
time.sleep(batch_delay)
# Combine all batches
if results:
print("\n Concatenating weather results... \n\n")
logger.info("Concatenating weather results...")
weather_data = pd.concat(results)
# Force completion of all pending operations
print("\n Finalizing all Earth Engine operations...")
ee.data.computeValue(ee.Number(1)) # This forces a sync point
print("\n Weather data processing complete.")
logger.info("Weather data processing complete.")
return weather_data
else:
print("No weather data to process.")
logger.warning("No weather data to process.")
return df
و برای هر دسته ای که پردازش شده است ، ما به save_results_to_downloads()
عملکرد برای بارگیری نتیجه ما در سناریویی که هنگام خراش داده ها خطایی رخ می دهد. این عملکرد با ایجاد جنبه مدیریت پرونده با ایجاد پویا ایجاد شده است temp_downloads
پوشه در فهرست بارگیری کاربر (یا هر مکان مشخص) به گونه ای که ما از پرونده های خروجی بازخورد فوری دریافت کرده و به طور مداوم پیشرفت خود را در یک مکان به راحتی قابل دسترسی ذخیره می کنیم.
def save_results_to_downloads(weather_data, filename='weather_data.csv', save_folder='temp_downloads'):
"""
Save results directly to temporary downloads folderArgs:
weather_data: DataFrame to save
filename: Name of the file to save
Returns:
Path where the file was saved
"""
# Save to new folder in Downloads or create it if it doesn't exist
relative_path = '~/Downloads'
expand = os.path.expanduser(relative_path)
save_path = f'{expand}/{save_folder}'
if not os.path.exists(save_path):
os.makedirs(save_path)
# Create full file path
full_path = os.path.join(save_path, filename)
# Save the DataFrame
weather_data.to_csv(full_path, index=False)
print(f"✅ Data successfully saved to: {full_path}")
به طور خلاصه ، رویکرد پردازش دسته ای ما مزایای مختلفی را ارائه می دهد:
- پیگیری پیشرفت: کاربران می توانند وضعیت پردازش را مشاهده کنند
- مقاومت در برابر خطا: دسته های شکست خورده کل روند را متوقف نمی کنند
- محدود کردن نرخ: از بیش از حد API جلوگیری می کند
- قابلیت رزومه: دسته های انفرادی صرفه جویی در اجازه از خرابی ها
4. اجرای اسکریپت
اکنون که ما بحث کرده ایم که چگونه تمام کارکردهای فردی نقش خود را در فرآیند استخراج داده ها ایفا می کنند ، اکنون می توانیم مرحله آخر را برای تهیه همه چیزهایی که ما در فیلمنامه اصلی اعدام آموخته ایم ، تصویب کنیم:
def main():
# Load environment variables
load_dotenv()# Authentication
# Get the secret project name from userdata
project_name = os.environ['PROJECT_NAME']
if not project_name:
raise ValueError("PROJECT_NAME environment variable is required. Please set it in your .env file.")
# Trigger the authentication flow.
ee.Authenticate()
# Initialize the library.
ee.Initialize(project=project_name)
start_time = time.time()
df = create_dataframe() #[:200]
datetime_col = input("\n Enter the column name of the DATETIME column in your dataset: ")
df["ignition_datetime"] = convert_float_to_datetime(df[datetime_col])
unique_id_col = input("\n Enter the column name of the column you wish to designate as the UNIQUE ID field for your dataset: ")
weather_data = process_dataframe(df, id_col=unique_id_col)
end_time = time.time()
print(f"Execution took {end_time - start_time:.2f} seconds, or {((end_time - start_time) / 60):.2f} minutes, or {((end_time - start_time) / 3600):.2f} hours")
save_results_to_downloads(weather_data)
if __name__ == "__main__":
main()
پایان
ولا اکنون شما یک ابزار قدرتمند برای غنی سازی مجموعه داده های آتش سوزی با اطلاعات آب و هوایی دارید. این امر امکانات بی شماری را برای تجزیه و تحلیل و مدل سازی باز می کند. در نظر بگیرید که ابزاری را برای شامل موارد زیر در نظر بگیرید:
- متغیرهای آب و هوایی اضافی (بارش ، فشار جوی)
- شاخص های پوشش گیاهی از تصاویر ماهواره ای
- داده های توپوگرافی (ارتفاع ، شیب)
- داده های پیرامونی آتش نشانی تاریخی
ترکیبی از مکان ، زمان ، آب و هوا و داده های زیست محیطی مجموعه داده های غنی را برای شما ایجاد می کند یادگیری ماشین برنامه های کاربردی در تحقیقات آتش سوزی و مدیریت ریسک.
با تشکر از شما برای خواندن تا پایان! لطفاً با تماس مستقیم با ما یا ترک نظرات در بخش نظر مقاله ، احساس راحتی کنید. همچنین ، kudos به مردمی در BC خدمات آتش سوزی چه کسی داده های حادثه تاریخی آتش سوزی را برای ما فراهم کرده است تا ابزار خود را در برابر آزمایش کنیم! و اگر می خواهید محتوای بیشتری برای کمک به شما در شروع تحقیقات مدیریت آتش سوزی خود داشته باشید ، ما از شما دعوت می کنیم تا خدمات پیش بینی آتش سوزی دولت BC را بررسی کنید (WPS) صفحه GitHub جایی که ما همچنان در مورد این موضوع آموزش هایی را ادامه خواهیم داد.
تا دفعه بعد
منتشر شده از طریق به سمت هوش مصنوعی