Spaces:
Sleeping
Sleeping
Fix column mismatch and improve error handling
Browse files- Made column parsing flexible to handle stations with different numbers of columns (7, 9, 12, etc.)
- Added missing columns as NaN when station has fewer columns than expected
- Improved error messages for station data fetching failures
- Removed Great Bear from dropdown as it's currently unavailable
- Added info note about Great Bear unavailability
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
app.py
CHANGED
|
@@ -77,11 +77,16 @@ def scrape_weather_data(site_id, hours=720):
|
|
| 77 |
|
| 78 |
print(f"Found {len(content['rows'] if content else [])} rows of data")
|
| 79 |
browser.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
return content
|
| 81 |
-
|
| 82 |
except Exception as e:
|
| 83 |
-
|
| 84 |
-
|
|
|
|
| 85 |
|
| 86 |
def parse_date(date_str):
|
| 87 |
"""Parse date string to datetime"""
|
|
@@ -95,15 +100,29 @@ def parse_weather_data(data):
|
|
| 95 |
"""Parse the weather data into a pandas DataFrame"""
|
| 96 |
if not data or 'rows' not in data:
|
| 97 |
raise ValueError("No valid weather data found")
|
| 98 |
-
|
| 99 |
df = pd.DataFrame(data['rows'])
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
|
| 108 |
numeric_cols = ['temp', 'dew_point', 'humidity', 'wind_chill', 'snow_depth',
|
| 109 |
'snowfall_3hr', 'snowfall_6hr', 'snowfall_24hr', 'swe']
|
|
@@ -324,11 +343,11 @@ with gr.Blocks(title="Weather Station Data Analyzer") as demo:
|
|
| 324 |
("Yellowstone Club - Andesite", "YCAND"),
|
| 325 |
("Yellowstone Club - American Spirit", "YCAMS"),
|
| 326 |
("Yellowstone Club - Base", "YCBAS"),
|
| 327 |
-
("Yellowstone Club - Great Bear", "YCGBR"),
|
| 328 |
("Bozeman Airport", "KBZN"),
|
| 329 |
("Salt Lake City", "KSLC")
|
| 330 |
],
|
| 331 |
-
value="YCTIM"
|
|
|
|
| 332 |
)
|
| 333 |
hours = gr.Number(
|
| 334 |
label="Hours of Data",
|
|
|
|
| 77 |
|
| 78 |
print(f"Found {len(content['rows'] if content else [])} rows of data")
|
| 79 |
browser.close()
|
| 80 |
+
|
| 81 |
+
if not content or not content.get('rows'):
|
| 82 |
+
raise ValueError(f"No data found for station {site_id}. Station may not exist or may not be reporting.")
|
| 83 |
+
|
| 84 |
return content
|
| 85 |
+
|
| 86 |
except Exception as e:
|
| 87 |
+
error_msg = f"Error scraping data for {site_id}: {str(e)}"
|
| 88 |
+
print(error_msg)
|
| 89 |
+
raise ValueError(error_msg)
|
| 90 |
|
| 91 |
def parse_date(date_str):
|
| 92 |
"""Parse date string to datetime"""
|
|
|
|
| 100 |
"""Parse the weather data into a pandas DataFrame"""
|
| 101 |
if not data or 'rows' not in data:
|
| 102 |
raise ValueError("No valid weather data found")
|
| 103 |
+
|
| 104 |
df = pd.DataFrame(data['rows'])
|
| 105 |
+
|
| 106 |
+
# Different stations have different numbers of columns
|
| 107 |
+
# Standard columns we expect (in order)
|
| 108 |
+
expected_columns = ['datetime', 'temp', 'dew_point', 'humidity', 'wind_chill',
|
| 109 |
+
'wind_dir', 'wind_speed', 'snow_depth', 'snowfall_3hr',
|
| 110 |
+
'snowfall_6hr', 'snowfall_24hr', 'swe']
|
| 111 |
+
|
| 112 |
+
# Get actual number of columns
|
| 113 |
+
num_cols = len(df.columns)
|
| 114 |
+
print(f"Data has {num_cols} columns")
|
| 115 |
+
|
| 116 |
+
# Assign column names based on actual number of columns
|
| 117 |
+
if num_cols <= len(expected_columns):
|
| 118 |
+
df.columns = expected_columns[:num_cols]
|
| 119 |
+
# Add missing columns with NaN values
|
| 120 |
+
for col in expected_columns[num_cols:]:
|
| 121 |
+
df[col] = np.nan
|
| 122 |
+
else:
|
| 123 |
+
# If more columns than expected, just use the first 12
|
| 124 |
+
df = df.iloc[:, :12]
|
| 125 |
+
df.columns = expected_columns
|
| 126 |
|
| 127 |
numeric_cols = ['temp', 'dew_point', 'humidity', 'wind_chill', 'snow_depth',
|
| 128 |
'snowfall_3hr', 'snowfall_6hr', 'snowfall_24hr', 'swe']
|
|
|
|
| 343 |
("Yellowstone Club - Andesite", "YCAND"),
|
| 344 |
("Yellowstone Club - American Spirit", "YCAMS"),
|
| 345 |
("Yellowstone Club - Base", "YCBAS"),
|
|
|
|
| 346 |
("Bozeman Airport", "KBZN"),
|
| 347 |
("Salt Lake City", "KSLC")
|
| 348 |
],
|
| 349 |
+
value="YCTIM",
|
| 350 |
+
info="Note: Great Bear (YCGBR) is currently unavailable"
|
| 351 |
)
|
| 352 |
hours = gr.Number(
|
| 353 |
label="Hours of Data",
|