6.7 KiB
6.7 KiB
In [ ]:
from pathlib import Path
import pandas as pd
DATA_PATH = Path("data/SMSSpamCollection")
if not DATA_PATH.exists():
raise FileNotFoundError(
"Missing data/SMSSpamCollection. Follow data/README.md to download "
"and extract the official UCI SMS Spam Collection."
)
In [ ]:
# TODO 1: load the tab-separated UCI file into raw_df.
# Use the column names label and message.
raw_df = None
# TODO 2: display the shape, first five rows, and raw label counts.
print("Raw shape:", None)
raw_df
In [ ]:
# TODO 3: normalize label whitespace and remove rows with missing or empty text.
audited_df = None
# TODO 4: count exact duplicate rows.
exact_duplicate_count = None
# TODO 5: find messages associated with more than one distinct label.
conflicting_messages = None
print("Exact duplicate rows:", exact_duplicate_count)
print("Conflicting message texts:", None)
In [ ]:
# TODO 6: remove every conflicting message and then remove exact duplicates.
clean_df = None
# TODO 7: map ham to 0 and spam to 1 in a new target column.
clean_df["target"] = None
print("Clean shape:", None)
print(clean_df["target"].value_counts().sort_index())
In [ ]:
# TODO 8: create character_count and word_count columns.
clean_df["character_count"] = None
clean_df["word_count"] = None
# TODO 9: calculate a summary indexed by label with count and median lengths.
length_summary = None
class_distribution = None
print(length_summary)
print("Class proportions:")
print(class_distribution)
In [ ]:
assert list(raw_df.columns) == ["label", "message"]
assert clean_df["message"].notna().all()
assert clean_df["message"].ne("").all()
assert set(clean_df["label"].unique()) == {"ham", "spam"}
assert set(clean_df["target"].unique()) == {0, 1}
assert not clean_df.duplicated(subset=["label", "message"]).any()
assert not clean_df["message"].isin(conflicting_messages).any()
assert class_distribution.loc["ham"] > class_distribution.loc["spam"]
assert {"character_count", "word_count"}.issubset(clean_df.columns)
print("✓ Lab 1 completed")