Machine Learning

How can you put HeatMap on real map with Python

Requires the easiest, engagement, and maintenance to introduce geospatial data, often turn to sky. This seeing with 2D separates the map into equal cells of the grid and uses color to represent the size of integrated data standards within cells.

The temperature of the country allows for the quickest spatial phenomena. Patterns are like collections, hotspots, vendors, or gradients are immediately clear. This format can be helpful for decision makers and the community, which may not know well without the effects of green mathematics.

Heatmaps can be developed for square cells (called Based on Grid or stop matrix Heatmaps) or solid “rates” continued “(called iphi or kernel density Heathmaps). The following maps indicate the true personality of the tornado start Places use both methods.

Example of Gride (Top) and Kernel-Density HeatMap (bottom) (by the writer)

If you put your eyes while you look at the top map, you should see the styles such as those in the map below.

I prefer the Heatmaps based on grid because the sharp, unique boundaries make it easy to compare the number of nearest cells, and out of the outdoors. “I also have a soft spot for their visual look as my first video game was Pong and Wollennstein 3D.

In addition, the Kernel Density Heathermaps can be very expensive and towards the installation parameters. Their appearance depends largely on the selected kernel work and bandwidth or radio. The best choice of parliament may be smooth or smooth data, good patterns.

In this case Successful Success Success The project, we will use the Python to make static-based Heatmaps, based on the Grid of Tornado in the United States.

Data

In this lesson, we will use Tornado data from National Ocean Oceanic and Atmospheric Administration A good community domain. He extends back in 1950, including Tornado to start and maintain places, size, injury, murder, financial costs, and more.

Details are available at the predicting Noaa's storm pain center. The CSV format of the CSV format, yellowed from the following, combines the 1950-2023 time. Don't bother to remove it. For convenience, give me a link to the application code.

From a bad NOAA page of data weather (by the writer)

This CSV file contains 29 columns almost 69,000 storms. You can find the color of the column names here. We will primarily work with the first zolorni areas (Slat, Slon), the year (yr), and stormstrum (Mag).

Installing libraries

You will want to install the Incess, Matplotlib, Pandas, and Geoops. The previous links give input instructions. We will also use a library, part of the geoopandas installation.

To find the index, this project used the following versions:

Python 3.10.18

NUPP 2.2.5

Mattplotlib 3.10.0

pandas 2.2.3

Geoopandas 1.0.1

Dissen 2.0.6

Simplified code

It does not take a lot of code to cover HeatMAP on a map. The following code shows the basic process, although most part of it is effective for the purpose of submit, such as the US data in low provinces and improve the appearance of the color bar.

In the following section, we will also increase this code to make additional sorting, hiring more ctants for easy reviews, and using the specific information.

# --- Plotting ---
print("Plotting results...")
fig, ax = plt.subplots(figsize=FIGURE_SIZE)
fig.subplots_adjust(top=0.85)  # Make room for titles.

# Plot state boundaries and heatmap:
clipped_states.plot(ax=ax, color='none', 
                    edgecolor='white', linewidth=1)
vmax = np.max(heatmap)
img = ax.imshow(heatmap.T,
                extent=[x_edges[0], x_edges[-1], 
                        y_edges[0], y_edges[-1]],
                origin='lower', 
                cmap=cmap, norm=norm, 
                alpha=1.0, vmin=0, vmax=vmax)

# Annotations:
plt.text(TITLE_X, TITLE_Y, 'Tornado Density Heatmap', 
         fontsize=22, fontweight='bold', ha='left')
plt.text(x=SUBTITLE_X, y=SUBTITLE_Y, s=(
         f'{START_YEAR}–{END_YEAR}    EF Magnitude 3–5    ' 
         f'{GRID_SIZE_MILES}×{GRID_SIZE_MILES} mile cells'),
         fontsize=15, ha='left')
plt.text(x=SOURCE_X, y=SOURCE_Y, 
         s='Data Source: NOAA Storm Prediction Center',
         color='white', fontsize=11, 
         fontstyle='italic', ha='left')

# Clean up the axes:
ax.set_xlabel('')
ax.set_ylabel('')
ax.axis('off')

# Post the Colorbar:
ticks = np.linspace(0, vmax, 6, dtype=int)
cbar = plt.colorbar(img, ax=ax, shrink=0.6, ticks=ticks)
cbar.set_label('nTornado Count per Grid Cell', fontsize=15)
cbar.ax.set_yticklabels(list(map(str, ticks)))

print(f"Saving plot as '{SAVE_FILENAME}'...")
plt.savefig(SAVE_FILENAME, bbox_inches='tight', dpi=SAVE_DPI)
print("Plot saved.n")
plt.show()

Here is the result:

Tonnado Density HeatMap for all listed listed areas (by the writer)

Extended code

The Next Python code was written in Juptetlab and is defined by cell.

To import libraries / supply libraries

After importing the required libraries, it describes the configuration series that allow us to easily modify the sorting process, map boundaries, dimensions of plan, and more. In this analysis, focused on paperwork within the humanity, filters provinces and AF3 outside the universe for improved 1950 Dataset cells.

import matplotlib.pyplot as plt
import pandas as pd
import geopandas as gpd
import numpy as np
from shapely.geometry import box


# --- Configuration Constants ---
# Data URLs:
TORNADO_DATA_URL = '
STATES_DATA_URL = ("
                   "tl_2020_us_state.zip")

# Geographic Filtering:
EXCLUDED_STATES_ABBR = ['AK', 'HI', 'PR', 'VI']
TORNADO_MAGNITUDE_FILTER = [3, 4, 5]

# Year Filtering (inclusive):
START_YEAR = 1950
END_YEAR = 2023

# Coordinate Reference Systems (CRS):
CRS_LAT_LON = "EPSG:4326"  # WGS 84 geographic CRS (lat/lon)
CRS_ALBERS_EQUAL_AREA = "EPSG:5070"  # NAD83/Conus Albers (projected CRS in m)

# Box for Contiguous US (CONUS) in Albers Equal Area (EPSG:5070 meters):
CONUS_BOUNDS_MIN_X = -2500000
CONUS_BOUNDS_MIN_Y = 100000
CONUS_BOUNDS_MAX_X = 2500000
CONUS_BOUNDS_MAX_Y = 3200000

# Grid Parameters for Heatmap (50x50 mile cells):
GRID_SIZE_MILES = 50
HEATMAP_GRID_SIZE = 80500  # ~50 miles in meters.

# Plotting Configuration:
FIGURE_SIZE = (15, 12)
SAVE_DPI = 600
SAVE_FILENAME = 'tornado_heatmap.png'

# Annotation positions (in EPSG:5070 meters, relative to plot extent):
TITLE_X = CONUS_BOUNDS_MIN_X
TITLE_Y = CONUS_BOUNDS_MAX_Y + 250000  # Offset above max Y
SUBTITLE_X = CONUS_BOUNDS_MIN_X
SUBTITLE_Y = CONUS_BOUNDS_MAX_Y + 100000  # Offset above max Y
SOURCE_X = CONUS_BOUNDS_MIN_X + 50000  # Slightly indented from min X
SOURCE_Y = CONUS_BOUNDS_MIN_Y + 20000  # Slightly above min Y

Defining helper works

The following cell describes the functions of two upload services and data filters and downloads state boundaries. Note that we call Constants last time in the process.

# --- Helper Functions ---
def load_and_filter_tornado_data():
    """Load data, apply filters, and create a GeoDataFrame."""
    print("Loading and filtering tornado data...")
    df_raw = pd.read_csv(TORNADO_DATA_URL)
    
    # Combine filtering steps into one chained operation:
    mask = (~df_raw['st'].isin(EXCLUDED_STATES_ABBR) &
            df_raw['mag'].isin(TORNADO_MAGNITUDE_FILTER) &
            (df_raw['yr'] >= START_YEAR) & (df_raw['yr'] <= END_YEAR))
    df = df_raw[mask].copy()
    
    # Create and project a GeoDataFrame:
    geometry = gpd.points_from_xy(df['slon'], df['slat'], 
                                  crs=CRS_LAT_LON)
    temp_gdf = gpd.GeoDataFrame(df, geometry=geometry).to_crs(
                                CRS_ALBERS_EQUAL_AREA)
    return temp_gdf


def load_and_filter_states():
    """Load US state boundaries and filter for CONUS."""
    print("Loading state boundary data...")
    states_temp_gdf = gpd.read_file(STATES_DATA_URL)
    states_temp_gdf = (states_temp_gdf[~states_temp_gdf['STUSPS']
                  .isin(EXCLUDED_STATES_ABBR)].copy())
    states_temp_gdf = states_temp_gdf.to_crs(CRS_ALBERS_EQUAL_AREA)
    return states_temp_gdf

Note that tilde (~) in front of the mask and states_temp_gdf Talks enter the results, so we choose lines where the state summary is in the list provided outside.

Help Services for Help and Produces HeatMap

The following cell calls assistant duties to upload and filter data and block data into map boundaries, generate HeatMAP (by letter histogram2d() method), and explain the continuing colormap heating. Note that we also call the constants last time in the process.

# --- Data Loading and Preprocessing ---
gdf = load_and_filter_tornado_data()
states_gdf = load_and_filter_states()

# Create bounding box and clip state boundaries & tornado points:
conus_bounds_box = box(CONUS_BOUNDS_MIN_X, CONUS_BOUNDS_MIN_Y,
                       CONUS_BOUNDS_MAX_X, CONUS_BOUNDS_MAX_Y)
clipped_states = gpd.clip(states_gdf, conus_bounds_box)
gdf = gdf[gdf.geometry.within(conus_bounds_box)].copy()

# --- Heatmap Generation ---
print("Generating heatmap bins...")
x_bins = np.arange(CONUS_BOUNDS_MIN_X, CONUS_BOUNDS_MAX_X + 
                   HEATMAP_GRID_SIZE, HEATMAP_GRID_SIZE)
y_bins = np.arange(CONUS_BOUNDS_MIN_Y, CONUS_BOUNDS_MAX_Y + 
                   HEATMAP_GRID_SIZE, HEATMAP_GRID_SIZE)

print("Computing 2D histogram...")
heatmap, x_edges, y_edges = np.histogram2d(gdf.geometry.x, 
                                           gdf.geometry.y, 
                                           bins=[x_bins, y_bins])

# Define continuous colormap (e.g., 'hot', 'viridis', 'plasma', etc.):
print("Defining continuous colormap...")
cmap = plt.cm.hot
norm = None

print("Finished execution.")

Because this process can take a few seconds, print() The function keeps us up to date with program development:

Loading and filtering tornado data...
Loading state boundary data...
Generating heatmap bins...
Computing 2D histogram...
Defining continuous colormap...
Finished execution.

Planning the results

The last cell produces and saves conspiracy. Matplotlib's imshow() The path is charged with planning HeutMAP. To find out more imshow()Look at this article.

# --- Plotting ---
print("Plotting results...")
fig, ax = plt.subplots(figsize=FIGURE_SIZE)
fig.subplots_adjust(top=0.85)  # Make room for titles.

# Plot state boundaries and heatmap:
clipped_states.plot(ax=ax, color='none', 
                    edgecolor='white', linewidth=1)
vmax = np.max(heatmap)
img = ax.imshow(heatmap.T,
                extent=[x_edges[0], x_edges[-1], 
                        y_edges[0], y_edges[-1]],
                origin='lower', 
                cmap=cmap, norm=norm, 
                alpha=1.0, vmin=0, vmax=vmax)

# Annotations:
plt.text(TITLE_X, TITLE_Y, 'Tornado Density Heatmap', 
         fontsize=22, fontweight='bold', ha='left')
plt.text(x=SUBTITLE_X, y=SUBTITLE_Y, s=(
         f'{START_YEAR}–{END_YEAR}    EF Magnitude 3–5    ' 
         f'{GRID_SIZE_MILES}×{GRID_SIZE_MILES} mile cells'),
         fontsize=15, ha='left')
plt.text(x=SOURCE_X, y=SOURCE_Y, 
         s='Data Source: NOAA Storm Prediction Center',
         color='white', fontsize=11, 
         fontstyle='italic', ha='left')

# Clean up the axes:
ax.set_xlabel('')
ax.set_ylabel('')
ax.axis('off')

# Post the Colorbar:
ticks = np.linspace(0, vmax, 6, dtype=int)
cbar = plt.colorbar(img, ax=ax, shrink=0.6, ticks=ticks)
cbar.set_label('nTornado Count per Grid Cell', fontsize=15)
cbar.ax.set_yticklabels(list(map(str, ticks)))

print(f"Saving plot as '{SAVE_FILENAME}'...")
plt.savefig(SAVE_FILENAME, bbox_inches='tight', dpi=SAVE_DPI)
print("Plot saved.n")
plt.show()

This produces the following map:

Tornado Density Map of EF 3-5 Tornado First Places (by the writer)

This is a good map and teach more than a different way of kde.

Adding Last Tosnado Lasts

Our Tornado Density Heatmaps are based on start storm surfaces. But storms go after touching down. Tomnadado typical of 3 miles[3·namileslongbutwhenyoulookatstrongstormspricesareincreasingEF-3stormsbetween18milesandlowerEF-4between27milesThelongtrackstormsarerarehoweverbecomeslessthan2%ofallstorms

Because Tornado track length is less than 50 feet of our grid cells, we can expect them to cover one or two cells. Therefore, including the end of the end of Tornado should help improve our difficulty measurement.

To do this, we will need to combine the start of Lat-Lon areas – sift ENDPOINTS share with The same cell as their points that are relevant. If not, we will double “when calculated. The code for this is long, so I have kept it on this gire.

Here's just the “Start's” Map “for the associated areas with conclusions:

The prisiments of the Heatmap of the first (top) with the HeatMap to start and storage (down) (by the writer)

Common spirits are driving the majority of Thornadoes to the east and northeast. You can see the impact in the region like Missouri, Mississippi, Alabama and Tennessee. These areas have bright cells on the map below because of the storms that start in one cell and end in the closest cell. Note that the top number of storms in the group provided is up to 29 (map of high) to 33 (on the map below).

Like

We have used Python, pandas, geopanda, and the matplotlib project and hasts Heatmaps in the country maps. Geospatial Heatmops is the most effective way to visualize regional styles, patterns, hotspots, and issuing from mathematical details.

If you enjoy these types of projects, make sure you check my book, Real World Python: Hacker Guide to solve problems with codefound in bookstores and internet.

Source link

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button