def get_overall_ranges(df_all, years_range):
"""Calculate min/max values for yield and uncertainty across all years."""
all_predictions = []
all_uncertainties = []
for year in years_range:
X_test = np.load(save_path + str(year) + '_X.npy')
X_test = normalize_data(X_test, X_mean, X_std)
predictions = model.predict(X_test)
all_predictions.extend(predictions[:, 0])
all_uncertainties.extend(predictions[:, 1])
return {
'yield_min': np.min(all_predictions),
'yield_max': np.max(all_predictions),
'uncertainty_min': np.min(all_uncertainties),
'uncertainty_max': np.max(all_uncertainties)
}
def plot_yield_prediction(counties, year, value_ranges, figsize=(8, 6), show_coords=True):
"""
Create yield prediction map with less dense ticks
"""
yield_colors = ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4',
'#4eb3d3', '#2b8cbe', '#0868ac', '#084081']
yield_cmap = LinearSegmentedColormap.from_list('yield_professional', yield_colors)
fig, ax = plt.subplots(1, 1, figsize=figsize)
# Plot counties
counties.boundary.plot(ax=ax, linewidth=0.2, color='#666666', alpha=0.8)
counties.plot(column='Predicted_Yield',
ax=ax,
cmap=yield_cmap,
vmin=value_ranges['yield_min'],
vmax=value_ranges['yield_max'],
edgecolor='none')
if show_coords:
bounds = counties.total_bounds
ax.set_xlim(bounds[0], bounds[2])
ax.set_ylim(bounds[1], bounds[3])
# Create less dense coordinate ticks
lon_range = bounds[2] - bounds[0]
lat_range = bounds[3] - bounds[1]
# Increase spacing for less dense ticks
if lon_range > 20:
lon_step = 5 # Changed from 2 to 5
lat_step = 2 # Changed from 1 to 2
elif lon_range > 10:
lon_step = 3 # For medium areas
lat_step = 2
else:
lon_step = 2 # For smaller areas
lat_step = 1
lon_ticks = np.arange(np.ceil(bounds[0]/lon_step)*lon_step, bounds[2], lon_step)
lat_ticks = np.arange(np.ceil(bounds[1]/lat_step)*lat_step, bounds[3], lat_step)
ax.set_xticks(lon_ticks)
ax.set_yticks(lat_ticks)
ax.set_xticklabels([f'{int(abs(x))}°W' for x in lon_ticks])
ax.set_yticklabels([f'{int(y)}°N' for y in lat_ticks])
ax.grid(True, alpha=0.3, linewidth=0.5, color='gray')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
else:
ax.axis('off')
# Add colorbar
sm = plt.cm.ScalarMappable(cmap=yield_cmap,
norm=plt.Normalize(vmin=value_ranges['yield_min'],
vmax=value_ranges['yield_max']))
cbar = plt.colorbar(sm, ax=ax, shrink=0.8, aspect=30, pad=0.02)
# cbar.set_label('Predicted Yield (bu/acre)', rotation=90, labelpad=15)
ax.set_title(f'Predicted Crop Yield (bu/ac) - {year}', fontweight='bold', pad=15)
return fig, ax
def plot_uncertainty(counties, year, value_ranges, figsize=(8, 6), show_coords=True):
"""
Create uncertainty map with less dense ticks
"""
uncertainty_colors = ['#053061', '#2166ac', '#4393c3', '#92c5de', '#d1e5f0',
'#f7f7f7', '#fddbc7', '#f4a582', '#d6604d', '#b2182b', '#67001f']
uncertainty_cmap = LinearSegmentedColormap.from_list('uncertainty_professional', uncertainty_colors)
fig, ax = plt.subplots(1, 1, figsize=figsize)
# Plot counties
counties.boundary.plot(ax=ax, linewidth=0.2, color='#666666', alpha=0.8)
counties.plot(column='Uncertainty',
ax=ax,
cmap=uncertainty_cmap,
vmin=value_ranges['uncertainty_min'],
vmax=value_ranges['uncertainty_max'],
edgecolor='none')
if show_coords:
bounds = counties.total_bounds
ax.set_xlim(bounds[0], bounds[2])
ax.set_ylim(bounds[1], bounds[3])
# Create less dense coordinate ticks (same logic as yield plot)
lon_range = bounds[2] - bounds[0]
lat_range = bounds[3] - bounds[1]
if lon_range > 20:
lon_step = 5 # Less dense
lat_step = 2
elif lon_range > 10:
lon_step = 3
lat_step = 2
else:
lon_step = 2
lat_step = 1
lon_ticks = np.arange(np.ceil(bounds[0]/lon_step)*lon_step, bounds[2], lon_step)
lat_ticks = np.arange(np.ceil(bounds[1]/lat_step)*lat_step, bounds[3], lat_step)
ax.set_xticks(lon_ticks)
ax.set_yticks(lat_ticks)
ax.set_xticklabels([f'{int(abs(x))}°W' for x in lon_ticks])
ax.set_yticklabels([f'{int(y)}°N' for y in lat_ticks])
ax.grid(True, alpha=0.3, linewidth=0.5, color='gray')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
else:
ax.axis('off')
# Add colorbar
sm = plt.cm.ScalarMappable(cmap=uncertainty_cmap,
norm=plt.Normalize(vmin=value_ranges['uncertainty_min'],
vmax=value_ranges['uncertainty_max']))
cbar = plt.colorbar(sm, ax=ax, shrink=0.8, aspect=30, pad=0.02)
# cbar.set_label('Prediction Uncertainty (bu/acre)', rotation=90, labelpad=15)
ax.set_title(f'Prediction Uncertainty (bu/ac) - {year}', fontweight='bold', pad=15)
return fig, ax
# Calculate overall ranges once
value_ranges = get_overall_ranges(df_all, range(2018, 2022))
# Create separate plots for each year
for year in range(2018, 2022):
# Load the shapefile
counties = gpd.read_file(save_path+'cb_2019_us_county_20m.shp')
# Get data for current year
df_year = df_all[df_all['Year'] == year]
# Load and process X data
X_test = np.load(save_path + str(year) + '_X.npy')
X_test = normalize_data(X_test, X_mean, X_std)
# Get predictions
predictions = model.predict(X_test)
mean_pred = predictions[:, 0]
std_pred = predictions[:, 1]
# Add predictions to dataframe
df_year['Predicted_Yield'] = mean_pred
df_year['Uncertainty'] = std_pred
# Merge data
df_year['GEOID'] = df_year['GEOID'].astype(str)
counties['GEOID'] = counties['GEOID'].astype(str)
counties = counties.merge(df_year, left_on='GEOID', right_on='GEOID')
# Create and save yield prediction plot
fig_yield, ax_yield = plot_yield_prediction(counties, year, value_ranges)
# save_individual_figures(fig_yield, year, 'yield_prediction', save_path)
plt.show()
# Create and save uncertainty plot
fig_uncertainty, ax_uncertainty = plot_uncertainty(counties, year, value_ranges)
# save_individual_figures(fig_uncertainty, year, 'uncertainty', save_path)
plt.show()
# Close figures to save memory
plt.close(fig_yield)
plt.close(fig_uncertainty)