Spaces:
Sleeping
Sleeping
Update flightprice.py
Browse files- flightprice.py +49 -45
flightprice.py
CHANGED
|
@@ -52,8 +52,7 @@ def get_day_quarter(hour):
|
|
| 52 |
else:
|
| 53 |
return 'Night'
|
| 54 |
|
| 55 |
-
# --- 2.
|
| 56 |
-
# We use this to help check if the Destination is in the Route string
|
| 57 |
CITY_TO_CODE = {
|
| 58 |
'Banglore': 'BLR', 'Bangalore': 'BLR',
|
| 59 |
'Delhi': 'DEL', 'New Delhi': 'DEL',
|
|
@@ -68,20 +67,6 @@ CITY_TO_CODE = {
|
|
| 68 |
def get_code(city):
|
| 69 |
return CITY_TO_CODE.get(city.strip(), city[:3].upper())
|
| 70 |
|
| 71 |
-
def is_route_valid(route_str, destination):
|
| 72 |
-
"""
|
| 73 |
-
Checks if the Destination (Name or Code) appears in the Route string.
|
| 74 |
-
"""
|
| 75 |
-
if pd.isna(route_str) or route_str == 'nan':
|
| 76 |
-
return False
|
| 77 |
-
|
| 78 |
-
route_upper = route_str.upper()
|
| 79 |
-
dest_name_upper = destination.upper()
|
| 80 |
-
dest_code = get_code(destination)
|
| 81 |
-
|
| 82 |
-
# Check if code (e.g., 'COK') or name (e.g., 'COCHIN') is in string
|
| 83 |
-
return (dest_code in route_upper) or (dest_name_upper in route_upper)
|
| 84 |
-
|
| 85 |
# Load Data
|
| 86 |
x_train, x_test, y_test = load_data()
|
| 87 |
model = load_model()
|
|
@@ -108,15 +93,20 @@ if page == "π° Price Prediction":
|
|
| 108 |
st.title("βοΈ Flight Price Prediction")
|
| 109 |
st.markdown("### Enter Flight Details")
|
| 110 |
|
|
|
|
|
|
|
|
|
|
| 111 |
c1, c2 = st.columns(2)
|
| 112 |
with c1:
|
| 113 |
st.subheader("Flight Info")
|
| 114 |
|
| 115 |
-
# Source
|
| 116 |
source = st.selectbox("Source", sorted(x_train['Source'].unique()))
|
|
|
|
| 117 |
|
| 118 |
-
# Destination
|
| 119 |
destination = st.selectbox("Destination", sorted(x_train['Destination'].unique()))
|
|
|
|
| 120 |
|
| 121 |
airline = st.selectbox("Airline", sorted(x_train['Airline'].unique()))
|
| 122 |
|
|
@@ -137,37 +127,42 @@ if page == "π° Price Prediction":
|
|
| 137 |
stops_val = 0
|
| 138 |
|
| 139 |
if 'Route' in x_train.columns:
|
| 140 |
-
#
|
| 141 |
-
#
|
| 142 |
-
#
|
| 143 |
-
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
-
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
-
# --- 2. VALIDATION ---
|
| 150 |
-
# Check if the route actually contains the destination
|
| 151 |
-
if is_route_valid(selected_route_raw, destination):
|
| 152 |
-
selected_route = selected_route_raw
|
| 153 |
-
stops_val = route_lookup.get(selected_route, 0)
|
| 154 |
-
st.metric("Total Stops", stops_val)
|
| 155 |
-
st.success("β
Valid Route")
|
| 156 |
-
else:
|
| 157 |
-
# Warning if user picks a route that doesn't go to their destination
|
| 158 |
-
st.warning(f"β οΈ **{selected_route_raw}** does not seem to contain **{destination}** ({get_code(destination)}). Please confirm if this is correct.")
|
| 159 |
-
# We allow them to proceed but with a warning, or you can block it:
|
| 160 |
-
# selected_route = None
|
| 161 |
-
selected_route = selected_route_raw
|
| 162 |
-
stops_val = route_lookup.get(selected_route, 0)
|
| 163 |
-
|
| 164 |
else:
|
| 165 |
-
|
|
|
|
|
|
|
|
|
|
| 166 |
else:
|
| 167 |
st.error("Route column missing.")
|
| 168 |
|
| 169 |
st.markdown("<br>", unsafe_allow_html=True)
|
| 170 |
|
|
|
|
|
|
|
|
|
|
| 171 |
if st.button("Predict Price", type="primary"):
|
| 172 |
if selected_route:
|
| 173 |
# Prepare Input
|
|
@@ -182,12 +177,12 @@ if page == "π° Price Prediction":
|
|
| 182 |
'Total_Stops': [stops_val]
|
| 183 |
})
|
| 184 |
|
| 185 |
-
# Align
|
| 186 |
final_input = pd.DataFrame(columns=x_train.columns)
|
| 187 |
for col in x_train.columns:
|
| 188 |
final_input.loc[0, col] = input_df.iloc[0].get(col, 0)
|
| 189 |
|
| 190 |
-
# Types
|
| 191 |
for col in final_input.columns:
|
| 192 |
if x_train[col].dtype == 'object':
|
| 193 |
final_input[col] = final_input[col].astype(str)
|
|
@@ -195,12 +190,21 @@ if page == "π° Price Prediction":
|
|
| 195 |
final_input[col] = pd.to_numeric(final_input[col])
|
| 196 |
|
| 197 |
try:
|
|
|
|
| 198 |
pred = model.predict(final_input)[0]
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
except Exception as e:
|
| 201 |
st.error(f"Error: {e}")
|
| 202 |
else:
|
| 203 |
-
st.error("
|
| 204 |
|
| 205 |
elif page == "π Model Evaluation":
|
| 206 |
st.title("Model Evaluation")
|
|
|
|
| 52 |
else:
|
| 53 |
return 'Night'
|
| 54 |
|
| 55 |
+
# --- 2. MAPPINGS (For UI Display Only) ---
|
|
|
|
| 56 |
CITY_TO_CODE = {
|
| 57 |
'Banglore': 'BLR', 'Bangalore': 'BLR',
|
| 58 |
'Delhi': 'DEL', 'New Delhi': 'DEL',
|
|
|
|
| 67 |
def get_code(city):
|
| 68 |
return CITY_TO_CODE.get(city.strip(), city[:3].upper())
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
# Load Data
|
| 71 |
x_train, x_test, y_test = load_data()
|
| 72 |
model = load_model()
|
|
|
|
| 93 |
st.title("βοΈ Flight Price Prediction")
|
| 94 |
st.markdown("### Enter Flight Details")
|
| 95 |
|
| 96 |
+
# ---------------------------------------------------------
|
| 97 |
+
# INPUT SECTION (Reactive - No Form)
|
| 98 |
+
# ---------------------------------------------------------
|
| 99 |
c1, c2 = st.columns(2)
|
| 100 |
with c1:
|
| 101 |
st.subheader("Flight Info")
|
| 102 |
|
| 103 |
+
# 1. Source Selection
|
| 104 |
source = st.selectbox("Source", sorted(x_train['Source'].unique()))
|
| 105 |
+
st.success(f"π« Code: **{get_code(source)}**")
|
| 106 |
|
| 107 |
+
# 2. Destination Selection
|
| 108 |
destination = st.selectbox("Destination", sorted(x_train['Destination'].unique()))
|
| 109 |
+
st.error(f"π¬ Code: **{get_code(destination)}**")
|
| 110 |
|
| 111 |
airline = st.selectbox("Airline", sorted(x_train['Airline'].unique()))
|
| 112 |
|
|
|
|
| 127 |
stops_val = 0
|
| 128 |
|
| 129 |
if 'Route' in x_train.columns:
|
| 130 |
+
# ---------------------------------------------------------
|
| 131 |
+
# DOUBLE FILTER LOGIC (Source AND Destination)
|
| 132 |
+
# ---------------------------------------------------------
|
| 133 |
+
# We query the dataframe for rows matching BOTH selected Source and Destination
|
| 134 |
+
filtered_routes = x_train[
|
| 135 |
+
(x_train['Source'] == source) &
|
| 136 |
+
(x_train['Destination'] == destination)
|
| 137 |
+
]['Route'].unique()
|
| 138 |
|
| 139 |
+
filtered_routes = sorted(filtered_routes.astype(str))
|
| 140 |
+
|
| 141 |
+
if len(filtered_routes) > 0:
|
| 142 |
+
# If routes exist, user selects one
|
| 143 |
+
selected_route = st.selectbox("Select Route", filtered_routes)
|
| 144 |
+
|
| 145 |
+
# Lookup hidden features based on this valid route
|
| 146 |
+
stops_val = route_lookup.get(selected_route, 0)
|
| 147 |
+
|
| 148 |
+
# Display Feedback
|
| 149 |
+
c_a, c_b = st.columns(2)
|
| 150 |
+
c_a.metric("Total Stops", stops_val)
|
| 151 |
+
c_b.success("β
Valid Route Found")
|
| 152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
else:
|
| 154 |
+
# No routes connect these two cities in the training data
|
| 155 |
+
st.error(f"π« No flights found from **{source}** to **{destination}** in the database.")
|
| 156 |
+
st.info("Try changing the Destination or Source.")
|
| 157 |
+
selected_route = None
|
| 158 |
else:
|
| 159 |
st.error("Route column missing.")
|
| 160 |
|
| 161 |
st.markdown("<br>", unsafe_allow_html=True)
|
| 162 |
|
| 163 |
+
# ---------------------------------------------------------
|
| 164 |
+
# PREDICTION BUTTON
|
| 165 |
+
# ---------------------------------------------------------
|
| 166 |
if st.button("Predict Price", type="primary"):
|
| 167 |
if selected_route:
|
| 168 |
# Prepare Input
|
|
|
|
| 177 |
'Total_Stops': [stops_val]
|
| 178 |
})
|
| 179 |
|
| 180 |
+
# Align Columns (Fill missing with 0)
|
| 181 |
final_input = pd.DataFrame(columns=x_train.columns)
|
| 182 |
for col in x_train.columns:
|
| 183 |
final_input.loc[0, col] = input_df.iloc[0].get(col, 0)
|
| 184 |
|
| 185 |
+
# Ensure Types
|
| 186 |
for col in final_input.columns:
|
| 187 |
if x_train[col].dtype == 'object':
|
| 188 |
final_input[col] = final_input[col].astype(str)
|
|
|
|
| 190 |
final_input[col] = pd.to_numeric(final_input[col])
|
| 191 |
|
| 192 |
try:
|
| 193 |
+
# Predict
|
| 194 |
pred = model.predict(final_input)[0]
|
| 195 |
+
real_price = np.expm1(pred)
|
| 196 |
+
|
| 197 |
+
# Show Result
|
| 198 |
+
st.markdown(f"""
|
| 199 |
+
<div style="background-color:#d4edda;padding:10px;border-radius:10px;border:2px solid #c3e6cb">
|
| 200 |
+
<h2 style="color:#155724;text-align:center;">π« Estimated Price: βΉ {real_price:,.2f}</h2>
|
| 201 |
+
</div>
|
| 202 |
+
""", unsafe_allow_html=True)
|
| 203 |
+
|
| 204 |
except Exception as e:
|
| 205 |
st.error(f"Error: {e}")
|
| 206 |
else:
|
| 207 |
+
st.error("Cannot predict without a valid route.")
|
| 208 |
|
| 209 |
elif page == "π Model Evaluation":
|
| 210 |
st.title("Model Evaluation")
|