Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
|
4 |
-
from nomad_data import country_emoji_map, data
|
5 |
|
6 |
# Create dataframe from imported data
|
7 |
df = pd.DataFrame(data)
|
@@ -72,6 +72,9 @@ def style_dataframe(df):
|
|
72 |
# Create a copy to avoid SettingWithCopyWarning
|
73 |
styled_df = df.copy()
|
74 |
|
|
|
|
|
|
|
75 |
# Convert to Styler object
|
76 |
styler = styled_df.style
|
77 |
|
@@ -124,6 +127,14 @@ def get_country_with_emoji(column):
|
|
124 |
choices_with_emoji.append(c)
|
125 |
return sorted(choices_with_emoji)
|
126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
# Initial styled dataframe
|
128 |
styled_df = style_dataframe(df)
|
129 |
|
@@ -199,6 +210,13 @@ with gr.Blocks(css="""
|
|
199 |
label="π Filter by Country"
|
200 |
)
|
201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
# Group all checkboxes together
|
203 |
visa_filter = gr.CheckboxGroup(
|
204 |
choices=["Has Digital Nomad Visa", "Visa Length β₯ 12 Months"],
|
@@ -212,14 +230,14 @@ with gr.Blocks(css="""
|
|
212 |
|
213 |
data_table = gr.Dataframe(
|
214 |
value=styled_df,
|
215 |
-
datatype=["str", "str", "number", "number", "number", "str", "number", "number", "str", "str"],
|
216 |
max_height=600,
|
217 |
interactive=False,
|
218 |
show_copy_button=True,
|
219 |
show_row_numbers=True,
|
220 |
show_search=True,
|
221 |
show_fullscreen_button=True,
|
222 |
-
pinned_columns=
|
223 |
)
|
224 |
|
225 |
# Update data when filters change
|
@@ -248,7 +266,7 @@ with gr.Blocks(css="""
|
|
248 |
return style_dataframe(filtered_df)
|
249 |
|
250 |
# Define advanced filters function
|
251 |
-
def apply_advanced_filters(country, cost, min_internet_speed, min_qol, visa_reqs, features):
|
252 |
# Process country filter
|
253 |
if country and country.startswith("βοΈ All"):
|
254 |
country = "All"
|
@@ -258,6 +276,15 @@ with gr.Blocks(css="""
|
|
258 |
country = country.split(" ", 1)[1]
|
259 |
break
|
260 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
filtered_df = df.copy()
|
262 |
|
263 |
# Basic filters (country and cost)
|
@@ -284,6 +311,10 @@ with gr.Blocks(css="""
|
|
284 |
if "Visa Length β₯ 12 Months" in visa_reqs:
|
285 |
filtered_df = filtered_df[filtered_df["Visa Length (Months)"] >= 12]
|
286 |
|
|
|
|
|
|
|
|
|
287 |
# Special features filters
|
288 |
if "Coastal Cities" in features:
|
289 |
coastal_keywords = ["coast", "beach", "sea", "ocean"]
|
@@ -303,32 +334,37 @@ with gr.Blocks(css="""
|
|
303 |
# Connect all filters to use the advanced filter function
|
304 |
country_dropdown.change(
|
305 |
apply_advanced_filters,
|
306 |
-
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features],
|
307 |
data_table
|
308 |
)
|
309 |
cost_slider.change(
|
310 |
apply_advanced_filters,
|
311 |
-
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features],
|
312 |
data_table
|
313 |
)
|
314 |
min_internet.change(
|
315 |
apply_advanced_filters,
|
316 |
-
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features],
|
317 |
data_table
|
318 |
)
|
319 |
min_quality.change(
|
320 |
apply_advanced_filters,
|
321 |
-
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features],
|
322 |
data_table
|
323 |
)
|
324 |
visa_filter.change(
|
325 |
apply_advanced_filters,
|
326 |
-
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features],
|
327 |
data_table
|
328 |
)
|
329 |
special_features.change(
|
330 |
apply_advanced_filters,
|
331 |
-
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features],
|
|
|
|
|
|
|
|
|
|
|
332 |
data_table
|
333 |
)
|
334 |
|
@@ -371,21 +407,24 @@ with gr.Blocks(css="""
|
|
371 |
|
372 |
if "Best Quality of Life" in priorities:
|
373 |
top_city = budget_filtered_df.sort_values("Quality of Life", ascending=False).iloc[0]
|
374 |
-
|
|
|
375 |
message += f"Monthly Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
376 |
message += f"Key Feature: {top_city['Key Feature']}"
|
377 |
recommendations.append(message)
|
378 |
|
379 |
if "Fastest Internet" in priorities:
|
380 |
top_city = budget_filtered_df.sort_values("Internet Speed (Mbps)", ascending=False).iloc[0]
|
381 |
-
|
|
|
382 |
message += f"Monthly Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
383 |
message += f"Key Feature: {top_city['Key Feature']}"
|
384 |
recommendations.append(message)
|
385 |
|
386 |
if "Most Affordable" in priorities:
|
387 |
top_city = budget_filtered_df.sort_values("Monthly Cost Living (USD)", ascending=True).iloc[0]
|
388 |
-
|
|
|
389 |
message += f"Quality of Life: {top_city['Quality of Life']}, Internet: {top_city['Internet Speed (Mbps)']} Mbps\n"
|
390 |
message += f"Key Feature: {top_city['Key Feature']}"
|
391 |
recommendations.append(message)
|
@@ -401,7 +440,8 @@ with gr.Blocks(css="""
|
|
401 |
df_temp['composite_score'] = (df_temp['quality_norm'] + df_temp['internet_norm'] + df_temp['cost_norm']) / 3
|
402 |
top_city = df_temp.sort_values("composite_score", ascending=False).iloc[0]
|
403 |
|
404 |
-
|
|
|
405 |
message += f"Quality: {top_city['Quality of Life']}, Internet: {top_city['Internet Speed (Mbps)']} Mbps, Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
406 |
message += f"Key Feature: {top_city['Key Feature']}"
|
407 |
recommendations.append(message)
|
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
|
4 |
+
from nomad_data import country_emoji_map, data, terrain_emoji_map
|
5 |
|
6 |
# Create dataframe from imported data
|
7 |
df = pd.DataFrame(data)
|
|
|
72 |
# Create a copy to avoid SettingWithCopyWarning
|
73 |
styled_df = df.copy()
|
74 |
|
75 |
+
# Apply terrain emojis
|
76 |
+
styled_df['Terrain'] = styled_df['Terrain'].apply(lambda x: terrain_emoji_map.get(x, x) if pd.notna(x) else x)
|
77 |
+
|
78 |
# Convert to Styler object
|
79 |
styler = styled_df.style
|
80 |
|
|
|
127 |
choices_with_emoji.append(c)
|
128 |
return sorted(choices_with_emoji)
|
129 |
|
130 |
+
# Add terrain filter function
|
131 |
+
def get_terrain_with_emoji():
|
132 |
+
terrains = ["β¨ All"]
|
133 |
+
for terrain in sorted(df["Terrain"].unique()):
|
134 |
+
if terrain in terrain_emoji_map:
|
135 |
+
terrains.append(terrain_emoji_map[terrain])
|
136 |
+
return terrains
|
137 |
+
|
138 |
# Initial styled dataframe
|
139 |
styled_df = style_dataframe(df)
|
140 |
|
|
|
210 |
label="π Filter by Country"
|
211 |
)
|
212 |
|
213 |
+
# Add terrain dropdown
|
214 |
+
terrain_dropdown = gr.Dropdown(
|
215 |
+
choices=get_terrain_with_emoji(),
|
216 |
+
value="β¨ All",
|
217 |
+
label="ποΈ Filter by Terrain"
|
218 |
+
)
|
219 |
+
|
220 |
# Group all checkboxes together
|
221 |
visa_filter = gr.CheckboxGroup(
|
222 |
choices=["Has Digital Nomad Visa", "Visa Length β₯ 12 Months"],
|
|
|
230 |
|
231 |
data_table = gr.Dataframe(
|
232 |
value=styled_df,
|
233 |
+
datatype=["str", "str", "str", "number", "number", "number", "str", "number", "number", "str", "str"],
|
234 |
max_height=600,
|
235 |
interactive=False,
|
236 |
show_copy_button=True,
|
237 |
show_row_numbers=True,
|
238 |
show_search=True,
|
239 |
show_fullscreen_button=True,
|
240 |
+
pinned_columns=3
|
241 |
)
|
242 |
|
243 |
# Update data when filters change
|
|
|
266 |
return style_dataframe(filtered_df)
|
267 |
|
268 |
# Define advanced filters function
|
269 |
+
def apply_advanced_filters(country, cost, min_internet_speed, min_qol, visa_reqs, features, terrain):
|
270 |
# Process country filter
|
271 |
if country and country.startswith("βοΈ All"):
|
272 |
country = "All"
|
|
|
276 |
country = country.split(" ", 1)[1]
|
277 |
break
|
278 |
|
279 |
+
# Process terrain filter
|
280 |
+
if terrain and terrain.startswith("β¨ All"):
|
281 |
+
terrain = "All"
|
282 |
+
else:
|
283 |
+
for emoji in ["ποΈ", "β°οΈ", "ποΈ", "ποΈ", "π΄", "ποΈ", "π²", "πΎ"]:
|
284 |
+
if terrain and emoji in terrain:
|
285 |
+
terrain = terrain.split(" ", 1)[1]
|
286 |
+
break
|
287 |
+
|
288 |
filtered_df = df.copy()
|
289 |
|
290 |
# Basic filters (country and cost)
|
|
|
311 |
if "Visa Length β₯ 12 Months" in visa_reqs:
|
312 |
filtered_df = filtered_df[filtered_df["Visa Length (Months)"] >= 12]
|
313 |
|
314 |
+
# Terrain filter
|
315 |
+
if terrain and terrain != "All":
|
316 |
+
filtered_df = filtered_df[filtered_df["Terrain"] == terrain]
|
317 |
+
|
318 |
# Special features filters
|
319 |
if "Coastal Cities" in features:
|
320 |
coastal_keywords = ["coast", "beach", "sea", "ocean"]
|
|
|
334 |
# Connect all filters to use the advanced filter function
|
335 |
country_dropdown.change(
|
336 |
apply_advanced_filters,
|
337 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
338 |
data_table
|
339 |
)
|
340 |
cost_slider.change(
|
341 |
apply_advanced_filters,
|
342 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
343 |
data_table
|
344 |
)
|
345 |
min_internet.change(
|
346 |
apply_advanced_filters,
|
347 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
348 |
data_table
|
349 |
)
|
350 |
min_quality.change(
|
351 |
apply_advanced_filters,
|
352 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
353 |
data_table
|
354 |
)
|
355 |
visa_filter.change(
|
356 |
apply_advanced_filters,
|
357 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
358 |
data_table
|
359 |
)
|
360 |
special_features.change(
|
361 |
apply_advanced_filters,
|
362 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
363 |
+
data_table
|
364 |
+
)
|
365 |
+
terrain_dropdown.change(
|
366 |
+
apply_advanced_filters,
|
367 |
+
[country_dropdown, cost_slider, min_internet, min_quality, visa_filter, special_features, terrain_dropdown],
|
368 |
data_table
|
369 |
)
|
370 |
|
|
|
407 |
|
408 |
if "Best Quality of Life" in priorities:
|
409 |
top_city = budget_filtered_df.sort_values("Quality of Life", ascending=False).iloc[0]
|
410 |
+
terrain_emoji = terrain_emoji_map.get(top_city['Terrain'], top_city['Terrain']).split()[0]
|
411 |
+
message = f"{terrain_emoji} {top_city['City']}, {top_city['Country']} - Quality of Life: {top_city['Quality of Life']}\n"
|
412 |
message += f"Monthly Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
413 |
message += f"Key Feature: {top_city['Key Feature']}"
|
414 |
recommendations.append(message)
|
415 |
|
416 |
if "Fastest Internet" in priorities:
|
417 |
top_city = budget_filtered_df.sort_values("Internet Speed (Mbps)", ascending=False).iloc[0]
|
418 |
+
terrain_emoji = terrain_emoji_map.get(top_city['Terrain'], top_city['Terrain']).split()[0]
|
419 |
+
message = f"{terrain_emoji} {top_city['City']}, {top_city['Country']} - Internet Speed: {top_city['Internet Speed (Mbps)']} Mbps\n"
|
420 |
message += f"Monthly Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
421 |
message += f"Key Feature: {top_city['Key Feature']}"
|
422 |
recommendations.append(message)
|
423 |
|
424 |
if "Most Affordable" in priorities:
|
425 |
top_city = budget_filtered_df.sort_values("Monthly Cost Living (USD)", ascending=True).iloc[0]
|
426 |
+
terrain_emoji = terrain_emoji_map.get(top_city['Terrain'], top_city['Terrain']).split()[0]
|
427 |
+
message = f"{terrain_emoji} {top_city['City']}, {top_city['Country']} - Monthly Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
428 |
message += f"Quality of Life: {top_city['Quality of Life']}, Internet: {top_city['Internet Speed (Mbps)']} Mbps\n"
|
429 |
message += f"Key Feature: {top_city['Key Feature']}"
|
430 |
recommendations.append(message)
|
|
|
440 |
df_temp['composite_score'] = (df_temp['quality_norm'] + df_temp['internet_norm'] + df_temp['cost_norm']) / 3
|
441 |
top_city = df_temp.sort_values("composite_score", ascending=False).iloc[0]
|
442 |
|
443 |
+
terrain_emoji = terrain_emoji_map.get(top_city['Terrain'], top_city['Terrain']).split()[0]
|
444 |
+
message = f"{terrain_emoji} {top_city['City']}, {top_city['Country']} - Balanced Choice\n"
|
445 |
message += f"Quality: {top_city['Quality of Life']}, Internet: {top_city['Internet Speed (Mbps)']} Mbps, Cost: ${top_city['Monthly Cost Living (USD)']}\n"
|
446 |
message += f"Key Feature: {top_city['Key Feature']}"
|
447 |
recommendations.append(message)
|