← Back to all projects Python · pandas · matplotlib

Medical Appointment No-Shows

Why do patients miss their appointments? I cleaned 110,000+ records, tested seven ideas, and found that waiting time matters far more than anything else.

ToolsPython · pandas · matplotlib · seaborn
Data110,527 appointments (public dataset)
Questions7 hypotheses tested
OutputFindings · recommendations
110,521Appointments analysed
20.2%Overall no-show rate
4.6% → 33%No-show: same day vs 31+ days
6Illogical rows removed
Step 1 · Cleaning

Getting the data trustworthy

Check quality

No nulls and no duplicates. I used describe() to look for odd values and found a negative age.

Remove impossible records

1 patient with age −1, and 5 appointments scheduled after the appointment day (all five were no-shows).

Why: they can’t be real, and keeping them would distort the rates.

Fix the structure

Renamed misspelt columns (Handcap, Hipertension, No-show), split date and time, and dropped the appointment time because it was always midnight.

Make flags consistent

The Handicap column held 0–4. The dataset describes it as true/false, so I turned it into 0/1 like the other condition columns.

Why: consistent flags make fair comparisons possible.

Step 2 · Analysis

Seven questions, seven answers

👩‍⚕️

Does gender matter?

No. Women had a 20.3% no-show rate and men 20.0%, a negligible gap.

🎂

Does age matter?

Yes. Ages 10–29 miss the most (about 24–25%). Ages 50–89 miss the least (about 15–17%).

🩺

Do medical conditions matter?

Patients with chronic conditions attend more: hypertension 17.3% vs 20.9%, diabetes 18.0% vs 20.4%.

💬

Do SMS reminders help?

Surprisingly, SMS recipients missed more (27.6% vs 16.7%). That led me to question causation.

⏳

Does waiting time matter?

Strongly. 4.6% for same-day, 24.1% for 1–7 days, 31.7% for 8–30 days and 33.0% for 31+ days.

📍

Does neighbourhood matter?

Somewhat: 8.6% to 28.9% among areas with 30+ appointments. I excluded tiny areas (1–2 appointments) that gave misleading 0% and 100% rates.

🔗

Do multiple conditions matter?

Attendance improves as conditions increase: 20.9% with none, 15.7% with three or more.

💡 The SMS result is not causal. Reminders mostly go to appointments booked far ahead, and those already have the highest no-show risk. Waiting time was the real driver.
Charts

The evidence

No-show rate by waiting time
No-show rate by waiting timeNearly 7× higher for 31+ days than for same-day appointments.
SMS received vs not
SMS received vs notThe counter-intuitive result that waiting time explains.
No-show rate by age group
No-show rate by age groupYoung adults miss the most. I merged ages 90+ because the sample was tiny.
With vs without each condition
With vs without each conditionHypertension and diabetes show the biggest gaps. Alcoholism shows almost none.
No-show rate by gender
No-show rate by genderAlmost identical for women and men.
Code sample

Cleaning and the waiting-time analysis

python · cleaning
# one record with a negative age
data.drop(data[data["Age"] < 0].index, inplace=True)

# fix column-name typos
data.rename(columns={"Handcap": "Handicap", "Hipertension": "Hypertension", "No-show": "No_show"}, inplace=True)

# appointments scheduled AFTER the appointment day make no sense
data.drop(data[data["Scheduled_Date"] > data["Appointment_Date"]].index, inplace=True)

# handicap should be yes/no like the other flags, not a count
data["Handicap"] = data["Handicap"].apply(lambda x: 1 if x > 0 else 0)
python · waiting time vs no-show
data["Waiting_Days"] = (pd.to_datetime(data["Appointment_Date"]) - pd.to_datetime(data["Scheduled_Date"])).dt.days

bins = [-1, 0, 7, 30, 179]
labels = ["Same day", "1-7 days", "8-30 days", "31+ days"]
data["Waiting_Group"] = pd.cut(data["Waiting_Days"], bins=bins, labels=labels)

noshow_by_waiting = data.groupby("Waiting_Group")["No_show"].apply(lambda x: (x == "Yes").mean() * 100).round(1)
print(noshow_by_waiting)
Conclusion

What drives missed appointments

⏳

Waiting time is the strongest factor

Longer delays lead to many more missed appointments.

🧑

Younger patients miss more

Older patients attend more consistently.

🩺

Chronic conditions mean better attendance

Probably because of routine follow-ups.

🚫

Gender has minimal impact

Gender-targeted campaigns aren’t justified.

Recommendations

What the clinic could do

1

Focus on long-wait appointments

Offer earlier slots or extra reminders for appointments booked more than 7 days ahead.

2

Redesign SMS reminders

Send more than one reminder for long-wait appointments (at booking and a few days before).

3

Target the 10–29 age group

Try channels young patients use, such as app notifications or WhatsApp.

4

Look into high no-show areas

Santos Dumont and Santa Cecília (about 28%) may have access barriers.

5

Borrow from chronic-care follow-up

Use similar tracking and reminder systems for all patients.

Project files

Download the notebook