Pandas Practical & Real Use Cases

Use Case #1 — Load and Inspect Messy City Service Data

A practical first inspection of a deliberately messy City Service Requests dataset using Pandas.

Una primera inspección práctica de un dataset deliberadamente sucio de solicitudes de servicios municipales usando Pandas.

Security notice: Run these scripts only in a controlled practice environment. Do not execute them in production, institutional folders, or live systems without authorization, backups, testing, least-privilege permissions, change control, and compliance with organizational protocols.
Aviso de seguridad: Ejecuta estos scripts únicamente en un ambiente controlado de práctica. No los corras en producción, carpetas institucionales ni sistemas activos sin autorización, respaldos, pruebas, permisos mínimos, control de cambios y cumplimiento de los protocolos organizacionales.

Business Scenario

Escenario de negocio

A city receives service requests through phone, web, email, mobile app, and walk-in channels. Before any analysis, the data analyst must understand the structure and identify missing values, duplicates, invalid formats, inconsistent categories, and suspicious values.

Una ciudad recibe solicitudes de servicio por teléfono, web, correo electrónico, aplicación móvil y atención presencial. Antes de analizar la información, el analista debe comprender su estructura e identificar valores faltantes, duplicados, formatos inválidos, categorías inconsistentes y valores sospechosos.

Learning Objectives

Objetivos de aprendizaje

Environment Verification

Verificación del entorno

python --version
python -c "import pandas as pd; print(pd.__version__)"
Python3.13.6
Pandas2.3.1
Dataset Rows530
Dataset Columns22

Project Files

Archivos del proyecto

FilePurposePropósito
messy_city_service_requests.csvMessy synthetic source dataset.Dataset sintético sucio de origen.
Pandas_Use_Case_01_Load_Inspect.pyPython inspection script.Script de inspección en Python.

Step 1 — Load the Dataset

import pandas as pd
from pathlib import Path

file_path = (
    Path.home()
    / "Documents"
    / "Pandas_Use_Cases"
    / "messy_city_service_requests.csv"
)

df = pd.read_csv(file_path)

print("\n" + "=" * 70)
print("DATASET LOADED SUCCESSFULLY")
print("=" * 70)

print(f"File: {file_path}")
print(f"Rows: {df.shape[0]:,}")
print(f"Columns: {df.shape[1]}")

Observed Result

Resultado observado

DATASET LOADED SUCCESSFULLY
File: C:\Users\jcarb\Documents\Pandas_Use_Cases\messy_city_service_requests.csv
Rows: 530
Columns: 22

Step 2 — Inspect Columns, Sample Rows, and Data Types

print("\n" + "=" * 70)
print("COLUMN NAMES")
print("=" * 70)

for position, column in enumerate(df.columns, start=1):
    print(f"{position:02}. {column}")

print("\n" + "=" * 70)
print("FIRST 10 ROWS")
print("=" * 70)

print(df.head(10).to_string(index=False))

print("\n" + "=" * 70)
print("DATA TYPES")
print("=" * 70)

print(df.dtypes)

Observed Result

Resultado observado

22 columns were detected.

Created_Date           object
Closed_Date            object
Latitude              float64
Longitude             float64
Estimated_Cost        float64
Resolution_Days         int64
Satisfaction_Score    float64

Key finding:
Created_Date and Closed_Date were loaded as text.

Key finding: Created_Date and Closed_Date were loaded as text, not as datetime values.

Hallazgo clave: Created_Date y Closed_Date fueron cargadas como texto, no como fechas.

Step 3 — Measure Missing Values

print("\n" + "=" * 70)
print("MISSING VALUES BY COLUMN")
print("=" * 70)

missing_summary = pd.DataFrame({
    "Missing_Count": df.isna().sum(),
    "Missing_Percent": (df.isna().mean() * 100).round(2)
})

missing_summary = missing_summary.sort_values(
    by="Missing_Count",
    ascending=False
)

print(missing_summary.to_string())

Observed Result

Resultado observado

Total Missing Values: 2,643

Example:
State missing values: 180

The result confirms that missing data is distributed across several columns and must be reviewed before cleaning.

Step 4 — Detect Exact Duplicates and Duplicated Request IDs

print("\n" + "=" * 70)
print("EXACT DUPLICATE ROWS")
print("=" * 70)

exact_duplicates = df.duplicated().sum()
print(f"Exact duplicate rows: {exact_duplicates}")

print("\n" + "=" * 70)
print("DUPLICATED REQUEST IDs")
print("=" * 70)

duplicated_request_ids = df["Request_ID"].duplicated(
    keep=False
).sum()

unique_duplicated_ids = df.loc[
    df["Request_ID"].duplicated(keep=False),
    "Request_ID"
].nunique()

print(f"Rows with duplicated Request_ID: {duplicated_request_ids}")
print(f"Unique duplicated Request_ID values: {unique_duplicated_ids}")

Observed Result

Resultado observado

Exact duplicate rows: 21
Rows with duplicated Request_ID: 58
Unique duplicated Request_ID values: 28

Interpretation:
The dataset contains both exact duplicated records and conflicting records that reuse the same business key.

Step 5 — Review Cardinality

print("\n" + "=" * 70)
print("UNIQUE VALUES BY COLUMN")
print("=" * 70)

unique_summary = df.nunique(dropna=False).sort_values()

print(unique_summary.to_string())

Observed Result

Resultado observado

State                   5
Description             6
Last_Name               7
Request_Channel         9
Satisfaction_Score      9
First_Name              9
Zip_Code               10
Department             10
City                   11
Status                 11
Priority               11
Service_Type           15
Request_ID            500

Interpretation:
Low-cardinality columns reveal category inconsistencies.
Request_ID has 500 unique values across 530 rows.

Cardinality helps reveal suspicious category fragmentation. For example, a single business concept may appear as Hialeah, HIALEAH, or with trailing spaces.

La cardinalidad ayuda a revelar fragmentación sospechosa de categorías. Por ejemplo, un mismo concepto puede aparecer como Hialeah, HIALEAH o con espacios adicionales.

Step 6 — Inspect Raw Category Values

print("\n" + "=" * 70)
print("DUPLICATED REQUEST ID SAMPLE")
print("=" * 70)

duplicate_id_sample = (
    df[df["Request_ID"].duplicated(keep=False)]
    .sort_values("Request_ID")
    .head(20)
)

print(
    duplicate_id_sample[
        [
            "Request_ID",
            "Created_Date",
            "Service_Type",
            "Department",
            "Status",
            "Priority",
            "Resolution_Days",
            "Satisfaction_Score"
        ]
    ].to_string(index=False)
)

print("\n" + "=" * 70)
print("RAW CATEGORY VALUES")
print("=" * 70)

category_columns = [
    "Service_Type",
    "Department",
    "Status",
    "Priority",
    "Request_Channel",
    "City",
    "State"
]

for column in category_columns:
    print(f"\n{column}:")
    print(df[column].value_counts(dropna=False).to_string())

Observed Result

Resultado observado

Request_Channel examples:
Website, Email, Walk-In, App, Phone, Web, Mobile App

City examples:
DORAL, Miami, Miami Lakes, Doral, Hialeah, HIALEAH, Miami-Lakes, MIAMI

State examples:
fl, Fla, Florida, FL, NaN

Interpretation:
The same business meaning appears under multiple spellings, cases, and formats.

Step 7 — Initial Data Quality Summary

print("\n" + "=" * 70)
print("INITIAL DATA QUALITY SUMMARY")
print("=" * 70)

total_rows = len(df)
total_columns = len(df.columns)
total_missing = int(df.isna().sum().sum())
exact_duplicates = int(df.duplicated().sum())
duplicate_request_rows = int(
    df["Request_ID"].duplicated(keep=False).sum()
)

summary = {
    "Total Rows": total_rows,
    "Total Columns": total_columns,
    "Total Missing Values": total_missing,
    "Exact Duplicate Rows": exact_duplicates,
    "Rows With Duplicated Request_ID": duplicate_request_rows,
    "Unique Request_ID Values": int(df["Request_ID"].nunique())
}

for item, value in summary.items():
    print(f"{item:<35}: {value:,}")

print("\n" + "=" * 70)
print("POTENTIAL DATA QUALITY ISSUES")
print("=" * 70)

issues = [
    "Created_Date and Closed_Date were loaded as text.",
    "Some records contain missing values.",
    "Exact duplicate rows exist.",
    "Some Request_ID values appear more than once.",
    "Text categories contain spelling, case, and spacing variations.",
    "Satisfaction_Score contains values outside the expected 1-5 range.",
    "Resolution_Days may contain negative or extreme values.",
    "Latitude and Longitude may contain invalid coordinates.",
    "Zip_Code, Email, and Phone require format validation."
]

for number, issue in enumerate(issues, start=1):
    print(f"{number:02}. {issue}")

Observed Result

Resultado observado

INITIAL DATA QUALITY SUMMARY

Total Rows                         : 530
Total Columns                      : 22
Total Missing Values               : 2,643
Exact Duplicate Rows               : 21
Rows With Duplicated Request_ID    : 58
Unique Request_ID Values           : 500

Nine potential data quality issues were identified for the next cleaning stages.

Observed Results

Resultados observados

Total Rows530
Total Columns22
Missing Values2,643
Exact Duplicates21
Rows with Duplicate ID58
Unique Request IDs500

Main Findings

Principales hallazgos

IssueProblema EvidenceEvidencia
Dates stored as textFechas almacenadas como texto Created_Date and Closed_Date = object
Missing informationInformación faltante 2,643 missing cells
Exact duplicatesDuplicados exactos 21 rows
Business-key duplicationDuplicación de clave de negocio 58 rows involved; 500 unique IDs in 530 rows
Category inconsistencyInconsistencia de categorías Examples: Hialeah / HIALEAH, FL / fl / Fla / Florida
Potential invalid valuesPosibles valores inválidos Scores outside 1–5, negative resolution days, invalid coordinates and contact formats

Professional Interpretation

Interpretación profesional

The objective of this use case is not to clean the data yet. The objective is to build an evidence-based understanding of the dataset before changing anything. This protects traceability, prevents premature assumptions, and creates a defensible baseline for the next cleaning steps.

El objetivo de este caso de uso todavía no es limpiar la información. El objetivo es construir una comprensión del dataset basada en evidencia antes de modificarlo. Esto protege la trazabilidad, evita suposiciones prematuras y crea una línea base defendible para los próximos pasos de limpieza.

Use Case #1 Completed

Caso de uso #1 completado

The dataset was loaded, profiled, and diagnosed successfully. The next logical step is to standardize text and category values in Use Case #2.

El dataset fue cargado, perfilado y diagnosticado correctamente. El siguiente paso lógico es estandarizar textos y categorías en el Caso de Uso #2.

More Community & Local Opportunity Resources

Más recursos comunitarios y oportunidades locales

Explore additional resources connected to local training, practical skills, employment opportunities, and community growth.

Explora recursos adicionales relacionados con capacitación local, habilidades prácticas, oportunidades de empleo y crecimiento comunitario.

HialeahOficios

Community-focused resources for trades, skills, local opportunities, and practical career development.

Recursos comunitarios enfocados en oficios, habilidades, oportunidades locales y desarrollo profesional práctico.

hialeahoficios.com

MiamiOficios

Miami-oriented resources for practical learning, employment pathways, and workforce development.

Recursos orientados a Miami para aprendizaje práctico, rutas de empleo y desarrollo de la fuerza laboral.

miamioficios.com