|
|
|
|
|
import gradio as gr |
|
|
import pandas as pd |
|
|
import numpy as np |
|
|
|
|
|
CSV_FILE = "all-vehicles-model@public.csv" |
|
|
|
|
|
|
|
|
COLS = { |
|
|
"make": "Make", |
|
|
"model": "Model", |
|
|
"fuel1": "Fuel Type1", |
|
|
"fuel_any": "Fuel Type", |
|
|
"drive": "Drive", |
|
|
"trans": "Transmission", |
|
|
"cyl": "Cylinders", |
|
|
"disp": "Engine displacement", |
|
|
"mpg_city_f1": "City Mpg For Fuel Type1", |
|
|
"mpg_hwy_f1": "Highway Mpg For Fuel Type1", |
|
|
"mpg_comb_f1": "Combined Mpg For Fuel Type1", |
|
|
"mpg_city_f2": "City Mpg For Fuel Type2", |
|
|
"mpg_hwy_f2": "Highway Mpg For Fuel Type2", |
|
|
"mpg_comb_f2": "Combined Mpg For Fuel Type2", |
|
|
"annual_fuel_cost_f1": "Annual Fuel Cost For Fuel Type1", |
|
|
"annual_fuel_cost_f2": "Annual Fuel Cost For Fuel Type2", |
|
|
"ev_range_f2": "Epa Range For Fuel Type2", |
|
|
"charge_240": "Time to charge at 240V", |
|
|
"co2_f1": "Co2 Fuel Type1", |
|
|
"co2_tailpipe_f1": "Co2 Tailpipe For Fuel Type1", |
|
|
"hatch_lug": "Hatchback luggage volume", |
|
|
"hatch_pass": "Hatchback passenger volume", |
|
|
"year": "Year" |
|
|
} |
|
|
|
|
|
def load_data(): |
|
|
df = pd.read_csv(CSV_FILE, sep=";", encoding="utf-8", engine="python") |
|
|
|
|
|
for c in ["City Mpg For Fuel Type1", "Highway Mpg For Fuel Type1", "Combined Mpg For Fuel Type1", |
|
|
"City Mpg For Fuel Type2", "Highway Mpg For Fuel Type2", "Combined Mpg For Fuel Type2", |
|
|
"Annual Fuel Cost For Fuel Type1", "Annual Fuel Cost For Fuel Type2", |
|
|
"Epa Range For Fuel Type2", "Time to charge at 240V", "Cylinders", "Engine displacement", |
|
|
"Hatchback luggage volume", "Hatchback passenger volume"]: |
|
|
if c in df.columns: |
|
|
df[c] = pd.to_numeric(df[c], errors="coerce") |
|
|
|
|
|
keep_cols = [v for v in COLS.values() if v in df.columns] |
|
|
subset = [c for c in keep_cols if c in ["Make","Model","Year"]] |
|
|
if subset: |
|
|
df = df.drop_duplicates(subset=subset) |
|
|
return df |
|
|
|
|
|
DF = load_data() |
|
|
|
|
|
def options_safe(col): |
|
|
if col in DF.columns: |
|
|
vals = DF[col].dropna().astype(str).str.strip().replace("", np.nan).dropna().unique().tolist() |
|
|
vals = [v for v in vals if v.lower() not in {"nan","none"}] |
|
|
vals.sort() |
|
|
return vals[:50] |
|
|
return [] |
|
|
|
|
|
FUEL_OPTS = sorted(set([*options_safe(COLS["fuel1"]), *options_safe(COLS["fuel_any"]), "No preference"])) |
|
|
DRIVE_OPTS = [*options_safe(COLS["drive"]), "No preference"] |
|
|
TRANS_OPTS = [*options_safe(COLS["trans"]), "No preference"] |
|
|
|
|
|
def recommend(budget_fuel_per_year, usage, daily_km, seats_min, fuel_pref, drive_pref, trans_pref, cargo_need, perf_pref): |
|
|
df = DF.copy() |
|
|
|
|
|
|
|
|
if fuel_pref and fuel_pref != "No preference": |
|
|
df = df[(df.get(COLS["fuel1"], "").astype(str).str.contains(fuel_pref, case=False, na=False)) | |
|
|
(df.get(COLS["fuel_any"], "").astype(str).str.contains(fuel_pref, case=False, na=False))] |
|
|
if drive_pref and drive_pref != "No preference" and COLS["drive"] in df.columns: |
|
|
df = df[df[COLS["drive"]].astype(str).str.contains(drive_pref, case=False, na=False)] |
|
|
if trans_pref and trans_pref != "No preference" and COLS["trans"] in df.columns: |
|
|
df = df[df[COLS["trans"]].astype(str).str.contains(trans_pref, case=False, na=False)] |
|
|
|
|
|
def norm(s): |
|
|
s = pd.to_numeric(s, errors="coerce") |
|
|
return (s - s.min()) / (s.max() - s.min() + 1e-9) |
|
|
|
|
|
|
|
|
if usage == "ืขืืจ": |
|
|
eff = df.get(COLS["mpg_city_f1"], df.get(COLS["mpg_comb_f1"])) |
|
|
elif usage == "ืืื ืขืืจืื ื": |
|
|
eff = df.get(COLS["mpg_hwy_f1"], df.get(COLS["mpg_comb_f1"])) |
|
|
else: |
|
|
eff = df.get(COLS["mpg_comb_f1"]) |
|
|
eff_score = norm(eff) if eff is not None else pd.Series(0, index=df.index) |
|
|
|
|
|
|
|
|
fuel_cost = df.get(COLS["annual_fuel_cost_f1"]) |
|
|
fuel_cost_score = 1 - norm(fuel_cost) if fuel_cost is not None else pd.Series(0.5, index=df.index) |
|
|
|
|
|
|
|
|
ev_range = df.get(COLS["ev_range_f2"]) |
|
|
if ev_range is not None and daily_km: |
|
|
ev_ok = (ev_range >= (daily_km * 0.62 * 3)) |
|
|
ev_score = ev_ok.astype(float) |
|
|
else: |
|
|
ev_score = pd.Series(0.5, index=df.index) |
|
|
|
|
|
|
|
|
cargo = df.get(COLS["hatch_lug"]) |
|
|
cargo_score = norm(cargo) if (cargo is not None and cargo_need) else pd.Series(0.5, index=df.index) |
|
|
|
|
|
|
|
|
cyl = df.get(COLS["cyl"]); disp = df.get(COLS["disp"]) |
|
|
perf_raw = norm(cyl).fillna(0.5) * 0.5 + norm(disp).fillna(0.5) * 0.5 |
|
|
econ_raw = 1 - perf_raw |
|
|
perf_mix = perf_pref * perf_raw + (1 - perf_pref) * econ_raw |
|
|
|
|
|
|
|
|
w_eff = 0.3 |
|
|
w_cost = 0.25 |
|
|
w_ev = 0.15 |
|
|
w_cargo = 0.1 |
|
|
w_perf = 0.2 |
|
|
|
|
|
score = w_eff*eff_score.fillna(0.5) + w_cost*fuel_cost_score.fillna(0.5) + w_ev*ev_score.fillna(0.5) + \ |
|
|
w_cargo*cargo_score.fillna(0.5) + w_perf*perf_mix.fillna(0.5) |
|
|
|
|
|
df_out = df.copy() |
|
|
df_out["Score"] = score.round(4) |
|
|
show_cols = [c for c in [ |
|
|
COLS["make"], COLS["model"], "Year" if "Year" in df.columns else None, |
|
|
COLS["fuel1"] if COLS["fuel1"] in df.columns else COLS["fuel_any"], |
|
|
COLS["drive"], COLS["trans"], |
|
|
COLS["mpg_city_f1"], COLS["mpg_hwy_f1"], COLS["mpg_comb_f1"], |
|
|
COLS["annual_fuel_cost_f1"], COLS["ev_range_f2"], |
|
|
COLS["cyl"], COLS["disp"], |
|
|
"Score" |
|
|
] if (c and (c in df.columns)) or c=="Score"] |
|
|
|
|
|
return df_out.sort_values("Score", ascending=False).head(10)[show_cols] |
|
|
|
|
|
with gr.Blocks(title="ืืืืืฅ ืจืืืื") as demo: |
|
|
gr.Markdown("# ืืืืืฅ ืจืืืื ืืื\nืืืคืืืงืฆืื ืืชืืืื ืืืืื ืืฆืจืืื ืฉืื ืขื ืืกืืก ืืืื ืฉื EPA.\n") |
|
|
|
|
|
with gr.Row(): |
|
|
usage = gr.Radio(["ืขืืจ", "ืืื ืขืืจืื ื", "ืืขืืจื"], value="ืืขืืจื", label="ืืืคื ืฉืืืืฉ") |
|
|
daily_km = gr.Slider(0, 200, value=30, step=5, label="ื ืกืืขื ืืืืืช ืืืืฆืขืช ืืงืืืืืืจืื") |
|
|
budget_fuel = gr.Slider(0, 6000, value=3000, step=100, label="ืชืงืฆืื ืืืง ืื ืืฉืื ืฉื ืชื") |
|
|
|
|
|
with gr.Row(): |
|
|
fuel_pref = gr.Dropdown(choices=FUEL_OPTS, value="No preference", label="ืขืืืคืืช ืืกืื ืืืง") |
|
|
drive_pref = gr.Dropdown(choices=DRIVE_OPTS, value="No preference", label="ืื ืขื") |
|
|
trans_pref = gr.Dropdown(choices=TRANS_OPTS, value="No preference", label="ืชืืืช ืืืืืืื") |
|
|
|
|
|
with gr.Row(): |
|
|
cargo_need = gr.Slider(0, 800, value=0, step=20, label="ื ืคื ืืืขื ืืื ืืืื ืจืฆืื") |
|
|
perf_pref = gr.Slider(0, 1, value=0.4, step=0.05, label="ืขืืืคืืช 0 ืืกืืื 1 ืืืฆืืขืื") |
|
|
seats_min = gr.Slider(2, 8, value=4, step=1, label="ืืืฉืืื ืืื ืืืื") |
|
|
|
|
|
btn = gr.Button("ืืฆื ืจืืืื") |
|
|
out = gr.Dataframe(interactive=False, wrap=True, label="ืืชืืืืช ืืืืืฆืืช . ืืืค 10") |
|
|
|
|
|
btn.click(fn=recommend, |
|
|
inputs=[budget_fuel, usage, daily_km, seats_min, fuel_pref, drive_pref, trans_pref, cargo_need, perf_pref], |
|
|
outputs=out) |
|
|
|
|
|
demo.queue().launch() |
|
|
|