Interactive dashboard for exploring ~50 years of U.S. railroad equipment accidents.
RailShield is a Dash-based visualization tool built on top of the Federal Railroad Administration's (FRA) Railroad Equipment Accident/Incident data. Users filter accidents by state, weather, visibility, track type, accident type, date, and time of day, plus numeric ranges for temperature, train speed, and trailing tonnage, and see the results reflected live across three linked views: a national map of accident locations, a line chart tracking a chosen attribute over time (split by accident type), and a bar chart showing the distribution of a chosen attribute.
- Martin Rashkov
- Petar Goranov
- Borislava Botseva
- Viktor Evgeniev
Built for JBI100 Visualization at Eindhoven University of Technology (Anna Vilanova & Stef van den Elzen). The course's three-assignment sequence follows Munzner's nested visualization design model: understanding the domain and dataset, defining goals/tasks and picking an implementation platform, then sketching and implementing the GUI and idioms.
- Filter panel: State, Weather, Visibility, Track type, Accident type (dropdowns); Temperature, Train speed, Trailing tons (range sliders); Date range and Time-of-day (range) pickers; one-click Reset Filters.
- Three linked views:
- Map: national scatter of accident locations; supports box/lasso selection to spatially cross-filter the other charts.
- Line chart: mean of a chosen continuous attribute per year, split by accident type.
- Bar chart: distribution (histogram) of a chosen attribute.
- Independent chart controls: dropdowns let you swap which attribute drives the line chart's category split, the line chart's y-axis mean, and the bar chart, without touching the sidebar filters.
- Cross-filtering by click: clicking into the line/bar charts filters casualty and on-duty-crew fields behind the scenes.
From our project presentation: a rail safety analyst wants to find the highest trailing-tonnage incidents in the corridor between New York and Chicago. They draw a lasso selection on the map between the two cities, which cross-filters the line and bar charts to that region. From there they can compare accident types and temperatures within just that selection, then hit Reset Filters to return to the full dataset. More broadly, the tool is meant to help spot trends and geographic concentrations of incidents across accident type, weather, and equipment conditions.
- Source: Federal Railroad Administration: Railroad Equipment Accident/Incident Source Data (Form 54) https://data.transportation.gov/Railroads/Railroad-Equipment-Accident-Incident-Source-DataF/aqxq-n5hy/about_data
- File used:
Railroad_Equipment_Accident_Incident_Source_Data__Form_54__20241026.csv(not included in this repo). Download it from the link above and place it indata/. - Coverage: accidents across U.S. states/territories, 1975‑01‑01 through 2024‑12‑31 (per the app's default date range).
- Cleaning (
data/data_cleaning.ipynb):- two-digit years corrected to four digits (
YEAR > 24 → 1900+YEAR, else2000+YEAR) - column set reduced from the full form to ~30 relevant attributes
- missing latitude/longitude substituted from a state-level lookup table when the
original coordinates are missing (flagged via a new
location_substitudedcolumn) - missing on-duty crew counts (
ENGRS,FIREMEN,CONDUCTR,BRAKEMEN) imputed with the column median - hour/minute combined into a single
time(0–24) field, with out-of-range values guarded against - derived
IDandpersonel(sum of on-duty crew roles) columns added
- two-digit years corrected to four digits (
- Dashboard: Python, Dash, Plotly, Pandas, NumPy
- Preprocessing: Seaborn, Matplotlib, PIL
railshield/
├── data/
│ ├── data_cleaning.ipynb # cleaning steps
│ └── data.csv # cleaned output
├── dashboard/
│ ├── assets/
│ │ ├── base.css
│ │ └── style.css
│ ├── views/
│ │ ├── barchart.py
│ │ ├── linechart.py
│ │ ├── mapplot.py
│ │ ├── menu.py
│ │ └── scatterplot.py
│ ├── config.py # filter option lists, default ranges, plot options
│ ├── data.py # data loading
│ ├── general.py
│ └── main.py
├── app.py # layout + callbacks
├── requirements.txt
└── README.md
git clone https://github.com/martinrashkov/railshield.git
cd railshield
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
pip install -r requirements.txt
# To start the dash app run:
python app.pyOpen the printed local URL in your browser.
To execute the data preprocessing, download the FRA CSV from the link in Data Source and place it where
dashboard/data.py expects it (check that file for the exact path/filename), then execute all cells of data_cleaning.ipynb.
- Hidden filter block: damage/casualty/on-duty-crew controls exist in
menu.pybut are hidden from the UI (see Features note above). - Unused
Scatterplotview:app.pyimportsjbi100_app.views.scatterplot.Scatterplotbut never instantiates or renders it in the layout — likely leftover from idiom exploration in Assignment 3. Either wire it in or remove it before publishing. - Suspicious
TEMPrange: the temperature slider spans -65 to 862, and the bar chart screenshot shows the vast majority of ~210k+ records landing in the lowest bin. 862°F is not a physically plausible ambient temperature, so this strongly suggests an unhandled sentinel/placeholder value (e.g. a missing-data code) in the rawTEMPcolumn that survived the cleaning notebook. Worth revisiting before treating that chart's output as meaningful. - Performance with the full ~50-year dataset at scale hasn't been documented — worth a line on load time / row count if you've tested it.
- Data: U.S. Federal Railroad Administration
- Course: JBI100 Visualization, TU Eindhoven, Anna Vilanova & Stef van den Elzen
- Initial code template: https://gitlab.tue.nl/JBI100/dashframework
This project's code is licensed under the MIT License.
Note this covers the code only. The underlying FRA dataset has its own U.S. government open-data terms, independent of the license on this repo. See Data Source for where to obtain it.

