import streamlit as st
import pandas as pd
import numpy as np
import openpyxl
from sklearn.neighbors import KNeighborsRegressor
from geopy.distance import geodesic
# Set wide mode
st.set_page_config(layout="wide")
# Set dark theme
st.markdown(
"""
""",
unsafe_allow_html=True
)
# Create a DataFrame with sample data
data = pd.read_excel('ven_ter_fim_PEDÓ.xlsx')
# 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
# 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(15 - np.log10(max_distance))
# Create a sidebar for controls
with st.sidebar:
# Display a title
st.title('avalia.se')
# Dropdown to select specific coordinates
selected_coords = st.selectbox('Selecione Coordenadas', ['Random', 'Custom'])
if selected_coords == 'Custom':
custom_lat = st.number_input('Enter Latitude', value=-29.45086)
custom_lon = st.number_input('Enter Longitude', value=-51.9847)
radius_visible = True # Show radius slider for custom coordinates
else:
custom_lat, custom_lon = data['latitude'].mean(), data['longitude'].mean()
radius_visible = False # Hide radius slider for random coordinates
# Slider for setting the zoom level
zoom_level = st.slider('Nível de zoom', min_value=1, max_value=15, value=zoom_level)
# 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)
if selected_coords == 'Custom' and radius_visible:
# Filter data based on the radius and drop NaN values
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()
# Apply KNN and get predicted Vunit values
predicted_vunit = knn_predict(filtered_data, 'Vunit', knn_features)
# Add predicted Vunit values to filtered_data
filtered_data['Predicted_Vunit'] = predicted_vunit
# Add a custom CSS class to the map container
st.markdown(f"""""", unsafe_allow_html=True)
# Wrap the map in a container with the custom CSS class
with st.container():
st.map(filtered_data, zoom=zoom_level, use_container_width=True)
# Function to apply KNN and return Vunit 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 Vunit for the filtered_data
predictions = knn.predict(filtered_data[features_columns])
return predictions
# Features columns for KNN
knn_features = ['latitude', 'longitude', 'Area'] # Add other relevant features
# Check if KNN should be applied
if selected_coords == 'Custom' and radius_visible:
# Apply KNN and get predicted Vunit values
predicted_vunit = knn_predict(data, 'Vunit', knn_features)
# Add predicted Vunit values to filtered_data
filtered_data['Predicted_Vunit'] = predicted_vunit
# Display the map and filtered_data
with st.container():
if selected_coords == 'Custom':
st.map(filtered_data, zoom=zoom_level, use_container_width=True)
# Display the predicted Vunit values if applicable
if 'Predicted_Vunit' in filtered_data.columns:
st.write("Predicted Vunit Values:")
st.write(filtered_data[['latitude', 'longitude', 'Vunit', 'Predicted_Vunit']])