Untitled

 avatar
unknown
python
10 months ago
4.4 kB
19
Indexable
#📦 Cell 1 — imports & constants
import pandas as pd
import numpy as np
from pathlib import Path
from sklearn.preprocessing import StandardScaler

DATA_DIR = Path("data")
TRAIN_CSV = DATA_DIR / "train.csv"
TEST_CSV  = DATA_DIR / "test.csv"

OUT_TRAIN = Path("processed_train.csv")
OUT_TEST  = Path("processed_test.csv")

#📥 Cell 2 — load the datasets
train = pd.read_csv(TRAIN_CSV)
test  = pd.read_csv(TEST_CSV)

# Keep a copy of original indices/ids if you want to sanity-check later
train_head = train.head(2)
test_head  = test.head(2)

train_head, test_head

#🧱 Cell 3 — fill NaNs in age with floor(mean)

The prompt says: “Fill the missing values in the age column with the mean age of the houses, rounded to the nearest lower integer.”
We compute the mean within each split (train/test) and floor it.

def fill_age_floor_mean(df: pd.DataFrame) -> pd.DataFrame:
    df = df.copy()
    if "age" in df.columns:
        # mean over non-missing values
        mean_val = df["age"].mean()
        # floor to nearest lower integer
        fill_val = int(np.floor(mean_val))
        df["age"] = df["age"].fillna(fill_val).astype(int)
    return df

train = fill_age_floor_mean(train)
test  = fill_age_floor_mean(test)
train["age"].dtype, test["age"].dtype

#🔢 Cell 4 — ordinal-encode condition_name to consecutive ints starting at 0

The unit tests only require consecutive integers starting at 0, not a global mapping.
Therefore, factorize each split independently so each set’s codes are {0, 1, ..., k-1}.

def encode_condition_consecutive(df: pd.DataFrame, col="condition_name") -> pd.DataFrame:
    df = df.copy()
    if col in df.columns:
        codes, uniques = pd.factorize(df[col], sort=False)  # order of appearance; starts at 0
        df[col] = codes.astype(int)
    return df

train = encode_condition_consecutive(train, "condition_name")
test  = encode_condition_consecutive(test, "condition_name")

train["condition_name"].unique(), test["condition_name"].unique()

#📏 Cell 5 — Standard scale sqft_living & sqft_lot (fit on train, transform both)

No leakage: fit scaler on train only, then apply to both.

scale_cols = ["sqft_living", "sqft_lot"]

scaler = StandardScaler()
# Fit on train using only the specified columns
scaler.fit(train[scale_cols])

# Transform both splits
train[scale_cols] = scaler.transform(train[scale_cols])
test[scale_cols]  = scaler.transform(test[scale_cols])

# Optional: small check of means/stds on train
float(train[scale_cols[0]].mean()), float(train[scale_cols[0]].std(ddof=0))

#💾 Cell 6 — save exactly as the grader expects
# Preserve all columns and the existing order
train.to_csv(OUT_TRAIN, index=False)
test.to_csv(OUT_TEST, index=False)

print(f"Wrote {OUT_TRAIN.resolve()}")
print(f"Wrote {OUT_TEST.resolve()}")

(train.shape, test.shape, list(train.columns))

#✅ (optional) Cell 7 — sanity checks that mirror the tests
# 1) Datasets are non-empty and contain expected columns
assert "house_id" in train.columns and "house_id" in test.columns, "house_id column missing"
assert "age" in train.columns and "condition_name" in train.columns, "Required columns missing"
assert "sqft_living" in train.columns and "sqft_lot" in train.columns, "Scaling columns missing"

# 2) Encoded column is int and codes are consecutive starting at 0 within each split
def assert_consecutive_codes(series: pd.Series):
    s = pd.Series(series).astype(int)
    codes = sorted(set(s.tolist()))
    assert codes[0] == 0, "codes must start at 0"
    for i in range(1, len(codes)):
        assert codes[i] == codes[i-1] + 1, "codes must be consecutive"

assert_consecutive_codes(train["condition_name"])
assert_consecutive_codes(test["condition_name"])

# 3) age is integer typed (imputation done)
assert pd.api.types.is_integer_dtype(train["age"]), "train.age must be integer dtype"
assert pd.api.types.is_integer_dtype(test["age"]),  "test.age must be integer dtype"

# 4) scaler: train columns roughly mean 0 / std 1
for c in scale_cols:
    m = abs(train[c].mean())
    # population std close to 1
    s = abs(train[c].std(ddof=0) - 1.0)
    assert m < 1e-6 and s < 1e-6 or (m < 1e-4 and s < 1e-4), f"{c} not standard scaled on train"

print("All sanity checks passed ✅")
Editor is loading...
Leave a Comment