An interactive visualization of hospital patient discharge statistics in Germany, broken down by federal state, age group, gender, and ICD-10 diagnosis category.
- Docker Desktop (includes Docker Compose)
Run these two commands from the project root directory:
docker compose build
docker compose up -dThen open http://localhost:8081 in your browser.
The database is populated automatically on first start — no manual import steps are needed.
docker compose down.
├── app/
│ ├── main.html # Single-page application shell
│ ├── main.css # All styling
│ ├── index.php # PHP router
│ ├── js/ # Frontend JavaScript modules
│ │ ├── main.js # App orchestration & zoom behavior
│ │ ├── render.js # D3 rendering (pie charts, grids, axes)
│ │ ├── sidebar.js # Diagnosis detail panel
│ │ ├── filter-ui.js # Filter panel
│ │ └── d3.min.js # Vendored D3.js library
│ ├── api/ # PHP REST API endpoints
│ ├── db/migrations/ # Database schema and seed SQL
│ └── dataset/ # Raw data, processed data, Python scripts
├── docs/ # Development documentation
├── docker-compose.yml
└── Dockerfile
Using official statistics from the German Federal Statistical Office (Destatis), the application lets users explore hospital patient discharge numbers across all 16 German federal states for the year 2024. Each data point can be filtered and examined by:
- Federal state — all 16 Bundesländer
- Age group — 22 age groups from birth (0–1) to 95+
- Gender — male and female
- ICD-10 diagnosis — the full international diagnosis classification hierarchy (groups → subgroups → individual codes)
The central design question driving the visualization: Does age or place of residence determine what you get treated for?
The data comes from the German Federal Statistical Office (Destatis), table 23131-0011:
Krankenhauspatient:innen: Deutschland, Jahre, Altersgruppen, Geschlecht, Behandlungsdiagnose (ICD 10)
Hospital patients: Germany, years, age groups, gender, treatment diagnosis (ICD 10)
- Source: Destatis Genesis Online — Table 23131-0011
- Publisher: Statistisches Bundesamt (Destatis)
- License: Data licence Germany – attribution – version 2.0 (dl-de/by-2-0)
- Raw file:
app/dataset/23131-0011_de.csv(31,819 lines, semicolon-delimited) - Coverage: ~17 million patient discharge records across all federal states, age groups, genders, and ~300 individual ICD-10 diagnosis codes
A supplementary population dataset (app/dataset/population.csv) was used to contextualize patient numbers relative to state population sizes.
Simple overview diagrams are developed in .
The application has two linked views that activate depending on zoom level:
At the default zoom level, the screen shows a grid of small pie charts. Each cell in the grid represents one combination of federal state (column) and age group (row). The pie chart inside shows the male-to-female ratio of hospital patients for that combination, with circle size proportional to the total number of patients.
This immediately makes visible, for example, that elderly age groups have far more female patients (partly due to longer life expectancy), and that some states have noticeably different age structures.
Zooming in transforms the view into a colored heat map where each cell is subdivided by ICD-10 diagnosis group. Clicking a diagnosis cell opens a sidebar showing:
- A ring/donut chart breaking down diagnosis subgroups
- A further gender split within each subgroup
- Drill-down to individual ICD-10 diagnosis codes
A filter panel allows narrowing the data by:
- Specific federal states (multi-select)
- Age range (slider)
- Gender
- Toggle between absolute patient numbers and numbers relative to state population
This section is relevant for running and evaluating the project technically.
| Layer | Technology |
|---|---|
| Frontend | HTML5, CSS3, JavaScript (ES6 modules), D3.js v5 |
| Backend | PHP 8.5 on Apache |
| Database | PostgreSQL 16 |
| Infrastructure | Docker & Docker Compose |
| Data processing | Python 3 (CSV → JSON → SQL pipeline) |
D3.js was chosen for its precise control over SVG rendering and its established role in information visualization. It is bundled directly into app/js/d3.min.js rather than loaded from a CDN, ensuring the application runs fully offline without an internet connection — which cannot be guaranteed in every grading or demo environment.
Docker provides a one-command setup that works identically on any machine, with no manual database configuration, PHP version management, or dependency installation required.
The raw CSV from Destatis has a complex hierarchical structure (state blocks, ICD-10 levels encoded via leading spaces). A custom Python script (convert_to_json.py) parses it into a structured JSON file, which a second script (generate_seed.py) converts into SQL INSERT statements. This seed data is automatically loaded into PostgreSQL on first startup.
Full documentation of these steps:
The PostgreSQL database uses a normalized schema with 7 tables:
gender, age_groups, federal_states
icd10_diagnosis_group → icd10_diagnosis_subgroup → icd10_diagnosis
number_patients (fact table linking all dimensions)
Schema definition: app/db/migrations/001_schema.sql
This code was coded with the assistance of the AI language model Sonnet 4.6, which was used for drafting and implementing revision. The author defined the requirements and remain responsible for the final version.