Data Analysis — noaa_storm_events_2024.csv
Interactive scatter plot of NOAA Storm Events 2024, with README documenting the dataset schema.
NOAA Storm Events 2024 Visualization
Interactive scatter plot visualization of NOAA storm events data for 2024.
Dataset Overview
- Filename:
noaa_storm_events_2024.csv - Rows: 69,801
- Columns: 11
- Description: Records of storm events across the United States in 2024, including event type, location, magnitude, injuries, deaths, and damage information.
Column Descriptions
begin_date
- Date when the storm event began
- Data type: Temporal
- Missing values: None observed in sample
state
- U.S. state where the event occurred
- Data type: Geographic identifiers
- Missing values: None observed in sample
cz_name
- County/zone name where the event occurred
- Data type: Geographic identifiers
- Missing values: None observed in sample
event_type
- Type of storm event (e.g., Thunderstorm Wind, Excessive Heat)
- Data type: Nominal
- Missing values: None observed in sample
magnitude
- Numeric measurement of the event's intensity
- Data type: Quantitative
- Missing values: Some entries have 0 values which may indicate unrecorded magnitude
magnitude_type
- Unit of measurement for the magnitude field
- Data type: Nominal
- Missing values: Many entries are empty
injuries
- Number of injuries caused by the event
- Data type: Quantitative
- Missing values: All values appear to be present but mostly 0
deaths
- Number of deaths caused by the event
- Data type: Quantitative
- Missing values: All values appear to be present but mostly 0
property_damage
- Estimated property damage in USD
- Data type: Quantitative
- Missing values: All values appear to be present but mostly 0
crop_damage
- Estimated crop damage in USD
- Data type: Quantitative
- Missing values: All values appear to be present but mostly 0
tor_f_scale
- Fujita scale rating for tornado events (empty for non-tornado events)
- Data type: Ordinal
- Missing values: Most entries are empty as this only applies to tornadoes
Visualization Mappings
- X-axis:
property_damage- Shows the financial impact of events on property - Y-axis:
crop_damage- Shows the financial impact of events on crops - Color encoding:
event_type- Categorizes events by type for comparison
These mappings were chosen because:
- Property damage and crop damage are both quantitative measures of economic impact
- They allow for meaningful comparison of events based on financial consequences
- Event type provides a natural categorical distinction for color encoding
Inspiration
Inspired by:
References:
Visualization Ideas
Property vs. Crop Damage Scatter with Log Scales
- Main question: Do property and crop damage scale together, or do events concentrate in one domain?
- Relevant data fields:
property_damage,crop_damage,event_type - Visual encoding: Scatter plot with symlog x and y axes (zeros handled), points colored by
event_type - Interaction/annotation: Toggle between linear and log scales; label the outlier points with the largest combined damage
- Implementation note: Use
d3.scaleSymlog()so zero-damage rows remain visible; load the CSV withd3.csv()and filter forNumber.isFiniteas inApp.jsx
Event Type Small Multiples of the Damage Scatter
- Main question: How does the damage pattern differ within each event type?
- Relevant data fields:
property_damage,crop_damage,event_type - Visual encoding: Grid of small scatter plots, one per top-N
event_type, sharing axes - Interaction/annotation: Click a panel to highlight it in the main view
- Implementation note: Compute groups with
d3.group(data, d => d.event_type), sort by count, and render each panel with the same scale domains
Monthly Event Count Stacked Area by Event Type
- Main question: When during 2024 do different event types peak?
- Relevant data fields:
begin_date,event_type - Visual encoding: Stacked area chart, x = month parsed from
begin_date, y = event count, colored byevent_type - Interaction/annotation: Brush a time range to filter the scatter plot
- Implementation note: Parse dates with
d3.timeParse('%Y-%m-%d')and bin withd3.timeMonth
Calendar Heatmap of Daily Event Counts
- Main question: Are there clusters of storm activity on specific days?
- Relevant data fields:
begin_date - Visual encoding: GitHub-style calendar grid of 2024 days, cell color = count of events
- Interaction/annotation: Hover a day to list its top event types in a tooltip
- Implementation note: Use
d3.timeDayto generate the day sequence andd3.scaleSequential(d3.interpolateYlOrRd)for color
State Choropleth of Total Property Damage
- Main question: Which states bear the greatest property damage burden?
- Relevant data fields:
state,property_damage - Visual encoding: Choropleth map (log color scale) aggregated by state
- Interaction/annotation: Click a state to filter the scatter plot to that state
- Implementation note: Requires a US states GeoJSON file, which is not in the project; if unavailable, substitute a sorted bar chart (idea 6)
Horizontal Bar Chart of Damage by State
- Main question: What is the ranked total of property and crop damage per state?
- Relevant data fields:
state,property_damage,crop_damage - Visual encoding: Stacked horizontal bars, property vs. crop damage segments, sorted by total
- Interaction/annotation: Hover for exact dollar values; click to filter
- Implementation note: Use
d3.rollupsto aggregate, thend3.scaleBandfor y andd3.scaleLogor linear for x
Top Counties Lollipop Chart
- Main question: Which county zones (
cz_name) recorded the most damage events? - Relevant data fields:
cz_name,state,property_damage - Visual encoding: Lollipop chart of the top 20 county zones by summed property damage, labeled with state
- Interaction/annotation: Label each lollipop with its event count
- Implementation note: Combine
cz_nameandstateinto a composite key to avoid duplicate county names
- Main question: Which county zones (
Event Type Frequency vs. Median Damage Bubble Chart
- Main question: Are frequent event types also the most damaging?
- Relevant data fields:
event_type,property_damage,crop_damage - Visual encoding: Bubble chart, x = event count, y = median property damage, radius = total crop damage
- Interaction/annotation: Hover to show the event type name and totals
- Implementation note: Use
d3.rollupwithd3.median; scale radius withd3.scaleSqrt
Parallel Coordinates of Impact Metrics
- Main question: How do injuries, deaths, and damage co-vary across events?
- Relevant data fields:
injuries,deaths,property_damage,crop_damage,event_type - Visual encoding: Parallel coordinates with one axis per metric (log scale), lines colored by
event_typeand low-opacity - Interaction/annotation: Brush each axis to filter rows
- Implementation note: Sample rows if rendering all 69,801 lines is too slow; use canvas instead of SVG
Injuries vs. Deaths Scatter with Jitter
- Main question: Do events with injuries also tend to have deaths?
- Relevant data fields:
injuries,deaths,event_type - Visual encoding: Jittered scatter (small random offsets on integer counts) colored by
event_type - Interaction/annotation: Show a count of overlapping points at each integer coordinate on hover
- Implementation note: Most values are 0, so add jitter with
d3.randomUniformand keep the true values in the tooltip
Magnitude Distribution Violin Plot by Event Type
- Main question: How does event magnitude vary by event type, and in which units?
- Relevant data fields:
magnitude,magnitude_type,event_type - Visual encoding: Violin or box plot per
event_type, separated bymagnitude_typevia a dropdown - Interaction/annotation: Dropdown to switch
magnitude_type; note that 0 values may indicate missing data - Implementation note: Compute kernel density manually or use a box plot with
d3.quantileif violins are too heavy
Magnitude vs. Property Damage Hexbin
- Main question: Does higher magnitude translate into higher property damage?
- Relevant data fields:
magnitude,property_damage,magnitude_type - Visual encoding: Hexagonal binning with log-scaled counts, filtered by one
magnitude_typeat a time - Interaction/annotation: Toggle between hexbin and raw scatter
- Implementation note: Use
d3-hexbinor compute bins manually; restrict to onemagnitude_typeto keep units consistent
Tornado F-Scale Damage Strip Plot
- Main question: How does property damage grow with Fujita scale rating for tornadoes?
- Relevant data fields:
tor_f_scale,property_damage,event_type - Visual encoding: Strip plot (beeswarm) with x =
tor_f_scaleas ordinal categories, y = log property damage - Interaction/annotation: Filter to tornado rows only; annotate the median for each category
- Implementation note: Filter
event_typecontaining "Tornado" or non-emptytor_f_scale; used3.beeswarmor a simple jitter
Deaths and Injuries Over Time Line Chart
- Main question: Is there a seasonal pattern in casualties?
- Relevant data fields:
begin_date,injuries,deaths - Visual encoding: Weekly line chart with two series (injuries, deaths), y on a shared axis
- Interaction/annotation: Mark weeks with the highest totals with labeled points
- Implementation note: Bucket with
d3.timeWeekand sum withd3.rollup
Sankey Diagram from Event Type to Damage Category
- Main question: Where does total damage flow, from event type to property vs. crop?
- Relevant data fields:
event_type,property_damage,crop_damage - Visual encoding: Sankey diagram with left nodes = top event types, right nodes = damage categories, link width = summed dollars
- Interaction/annotation: Hover a link for its dollar total
- Implementation note: Use
d3-sankeywith a grouped aggregation; limit to top 8 event types and bundle the rest as "Other"
Chord Diagram of State and Event Type Co-occurrence
- Main question: Which states share similar event-type profiles?
- Relevant data fields:
state,event_type - Visual encoding: Chord diagram of the top states, arc width = shared event counts
- Interaction/annotation: Click a state arc to highlight its ribbons
- Implementation note: Build the matrix with
d3.rollupon (state, event_type) pairs, then used3.chordDirectedord3.chord
Zero-Damage Rate Waffle Chart by Event Type
- Main question: What share of events by type recorded no damage at all?
- Relevant data fields:
event_type,property_damage,crop_damage - Visual encoding: Waffle chart (10x10 cells) per top event type, filled cells = events with nonzero damage
- Interaction/annotation: Hover to show exact counts
- Implementation note: Compute the zero share with
d3.mean; render cells withd3.rangein a grid
Ridge Plot of Log Property Damage by Event Type
- Main question: How do the damage distributions compare across event types?
- Relevant data fields:
property_damage,event_type - Visual encoding: Stacked ridgeline densities of log10(property_damage + 1), one row per top event type
- Interaction/annotation: Click a ridge to filter the main scatter to that type
- Implementation note: Compute a simple histogram-based density per type with
d3.bin, then draw withd3.area
Cumulative Damage Curve (Pareto Chart)
- Main question: What fraction of total damage comes from the top few percent of events?
- Relevant data fields:
property_damage,crop_damage - Visual encoding: Pareto chart; bars = individual event totals sorted descending, line = cumulative share
- Interaction/annotation: Mark the 80% threshold with a reference line and annotate the event count at that point
- Implementation note: Sort with
d3.sort, compute running sums withd3.cumsum-style reduction, and show only the top 500 events for legibility
Linked Scatter and Timeline with Brushing
- Main question: How do damage patterns change over the course of the year?
- Relevant data fields:
begin_date,property_damage,crop_damage,event_type - Visual encoding: Top panel = scatter of property vs. crop damage; bottom panel = daily event timeline; brushing in one filters the other
- Interaction/annotation: Brush a date range to recolor scatter points by event type; show a count summary
- Implementation note: Share filtered state through React
useStateinApp.jsx, and used3.brushXon the timeline andd3.brushon the scatter