GEO_DASH_TABS / app.py
fschwartzer's picture
Update app.py
f573577
raw
history blame
8 kB
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsRegressor
from geopy.distance import geodesic
import googlemaps
from geopy.exc import GeocoderTimedOut
# Function to calculate distance in meters between two coordinates
def calculate_distance(lat1, lon1, lat2, lon2):
coords_1 = (lat1, lon1)
coords_2 = (lat2, lon2)
return geodesic(coords_1, coords_2).meters
# Function to apply KNN and return V_oferta values
def knn_predict(df, target_column, features_columns, k=5):
# Separate features and target variable
X = df[features_columns]
y = df[target_column]
# Create KNN regressor
knn = KNeighborsRegressor(n_neighbors=k)
# Fit the model
knn.fit(X, y)
# Use the model to predict V_oferta for the filtered_data
predictions = knn.predict(df[features_columns])
return predictions
# Set wide mode
st.set_page_config(layout="wide")
# Set dark theme
st.markdown(
"""
<style>
@font-face {font-family: 'Quicksand';
src: url('font/Quicksand-VariableFont_wght.ttf') format('truetype');
}
body {
color: white;
background-color: #1e1e1e;
font-family: 'Quicksand', sans-serif;
}
.st-df-header, .st-df-body, .st-df-caption {
color: #f8f9fa; /* Bootstrap table header text color */
}
.st-eb {
background-color: #343a40; /* Streamlit exception box background color */
}
</style>
""",
unsafe_allow_html=True
)
# Create a DataFrame with sample data
data = pd.read_excel('ven_fim_PEDÓ_nov_23.xlsx)
# Initialize variables to avoid NameError
selected_coords = 'Direcionada'
radius_visible = True
custom_address_initial = 'Av. Senador Alberto Pasqualini, 177 - Centro, Lajeado - RS, 95900-034' # Initial custom address
custom_lat = data['latitude'].median()
custom_lon = data['longitude'].median()
radius_in_meters = 1500
filtered_data = data # Initialize with the entire dataset
# Find the maximum distance between coordinates
max_distance = 0
for index, row in data.iterrows():
distance = calculate_distance(row['latitude'], row['longitude'], data['latitude'].mean(), data['longitude'].mean())
if distance > max_distance:
max_distance = distance
# Calculate a zoom level based on the maximum distance
zoom_level = round(17 - np.log10(max_distance))
# Set font to 'Quicksand' for title_html
title_html = """
<style>
@font-face {font-family: 'Quicksand';
src: url('font/Quicksand-VariableFont_wght.ttf') format('truetype');
}
body {{
font-family: 'Quicksand', sans-serif;
}}
</style>
<span style='color: gray; font-size: 50px;'>aval</span>
<span style='color: white; font-size: 50px;'>ia</span>
<span style='color: gray; font-size: 50px;'>.NEXUS</span>
"""
# Set font to 'Quicksand' for factor_html
factor_html = """
<style>
@font-face {font-family: 'Quicksand';
src: url('font/Quicksand-VariableFont_wght.ttf') format('truetype');
}
body {{
font-family: 'Quicksand', sans-serif;
}}
</style>
<a href='https://huggingface.co/spaces/DavidSB/avaliaFACTOR' target='_blank' style='text-decoration: none; color: inherit;'>
<span style='color: gray; font-size: 20px;'>aval</span>
<span style='color: white; font-size: 20px;'>ia</span>
<span style='color: gray; font-size: 20px;'>.FACTOR</span>
"""
# Set font to 'Quicksand' for evo_html
evo_html = """
<style>
@font-face {font-family: 'Quicksand';
src: url('font/Quicksand-VariableFont_wght.ttf') format('truetype');
}
body {{
font-family: 'Quicksand', sans-serif;
}}
</style>
<a href='https://huggingface.co/spaces/DavidSB/avalia.EVO' target='_blank' style='text-decoration: none; color: inherit;'>
<span style='color: gray; font-size: 20px;'>aval</span>
<span style='color: white; font-size: 20px;'>ia</span>
<span style='color: gray; font-size: 20px;'>.EVO</span>
"""
# Create a sidebar for controls
with st.sidebar:
#st.title('avalia.se')
st.sidebar.markdown(title_html, unsafe_allow_html=True)
# Add a dropdown for filtering "Tipo"
selected_tipo = st.selectbox('Filtrar por Tipo', data['Tipo'].unique())
selected_coords = st.selectbox('Selecione o tipo de pesquisa', ['Ampla', 'Direcionada'])
if selected_coords == 'Direcionada':
custom_address = st.text_input('Informe o endereço', custom_address_initial)
radius_visible = True # Show radius slider for custom coordinates
# No need to initialize max_distance_all here
else:
custom_address = "Lajeado, Rio Grande do Sul, Brazil" # Default address
radius_visible = False # Hide radius slider for random coordinates
max_distance_all = 0 # Initialize max_distance_all here
max_distance_all = 0 # Initialize max_distance_all here
# Geocode the custom address using the Google Maps API
gmaps = googlemaps.Client(key='AIzaSyDoJ6C7NE2CHqFcaHTnhreOfgJeTk4uSH0') # Replace with your API key
try:
location = gmaps.geocode(custom_address)[0]['geometry']['location']
custom_lat, custom_lon = location['lat'], location['lng']
except (IndexError, GeocoderTimedOut):
st.error("Erro: Não foi possível geocodificar o endereço fornecido. Por favor, verifique e tente novamente.")
# Slider for setting the zoom level
if selected_coords == 'Direcionada':
zoom_level = st.slider('Nível de zoom', min_value=1, max_value=15, value=zoom_level)
else:
for index, row in data.iterrows():
distance_all = calculate_distance(row['latitude'], row['longitude'], data['latitude'].mean(), data['longitude'].mean())
if distance_all > max_distance_all:
max_distance_all = distance_all
# Calculate a zoom level based on the maximum distance of the entire dataset
zoom_level_all = round(15 - np.log10(max_distance_all))
# Slider for setting the zoom level based on the entire dataset
zoom_level = st.slider('Nível de zoom', min_value=1, max_value=15, value=zoom_level_all)
# Conditionally render the radius slider
if radius_visible:
radius_in_meters = st.slider('Selecione raio (em metros)', min_value=100, max_value=5000, value=1000)
# Links to other apps at the bottom of the sidebar
st.sidebar.markdown(factor_html, unsafe_allow_html=True)
st.sidebar.markdown(evo_html, unsafe_allow_html=True)
# Filter data based on the radius
if selected_coords == 'Direcionada':
filtered_data = data[data.apply(lambda x: calculate_distance(x['latitude'], x['longitude'], custom_lat, custom_lon), axis=1) <= radius_in_meters]
filtered_data = filtered_data.dropna() # Drop rows with NaN values
# Add a custom CSS class to the map container
st.markdown(f"""<style>
.map {{
width: 100%;
height: 100vh;
}}
</style>""", unsafe_allow_html=True)
# Check if KNN should be applied
if selected_coords == 'Direcionada' and radius_visible:
# Apply KNN and get predicted V_oferta values
predicted_V_oferta = knn_predict(filtered_data, 'V_oferta', ['latitude', 'longitude', 'Area']) # Update with your features
# Add predicted V_oferta values to filtered_data
filtered_data['Predicted_V_oferta'] = predicted_V_oferta
# Display the map and filtered_data
with st.container():
if selected_coords == 'Direcionada':
st.map(filtered_data, zoom=zoom_level, use_container_width=True)
elif selected_coords == 'Ampla':
st.map(data, zoom=zoom_level, use_container_width=True)
# Display the predicted V_oferta values if applicable
if 'Predicted_V_oferta' in filtered_data.columns:
st.write("Valores (R$/m²) previstos com algoritmo KNN:")
st.write(filtered_data[['latitude', 'longitude', 'V_oferta', 'Predicted_V_oferta']])