|
|
| 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() |
|
|