create an app that can takes a csv file (and default there is one prepared for user to test). inside the csv file there is x, and y columns, and a url columns for images (e.g. for imgur). X, y will be plotted as a scatter plot. when user click on the plot, the app will take the x, y inputs from user and find the nearest neighbor in the dataframe from the x, y coordinates, and display the imgur images associated with the xy link in another side by side plot
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.neighbors import NearestNeighbors
import io
from streamlit_plotly_events import plotly_events
import plotly.express as px
# Sample data creation for default testing
def create_sample_data():
np.random.seed(42)
n_samples = 20
x = np.random.uniform(0, 10, n_samples)
y = np.random.uniform(0, 10, n_samples)
# Sample imgur URLs (these are just examples)
image_urls = [
"https://i.imgur.com/bY5XMel.png",
"https://i.imgur.com/gHksBVP.png",
"https://i.imgur.com/3vQUj5R.png",
"https://i.imgur.com/zzIJpGC.png"
]
# Randomly assign image URLs
urls = np.random.choice(image_urls, n_samples)
df = pd.DataFrame({
'x': x,
'y': y,
'image_url': urls
})
return df
# Initialize session state for clicked point
if 'clicked_point' not in st.session_state:
st.session_state.clicked_point = None
st.title("Interactive Scatter Plot with Images")
# File uploader
uploaded_file = st.file_uploader("Upload your CSV file (should contain x, y, and image_url columns)", type=['csv'])
# Load data
if uploaded_file is not None:
df = pd.read_csv(uploaded_file)
else:
st.write("Using sample data for demonstration. Upload your own CSV file to use your data.")
df = create_sample_data()
# Display the dataframe
st.write("Dataset:")
st.dataframe(
df,
column_config={
"image_url": st.column_config.ImageColumn(
"Preview",
help="Image preview"
)
}
)
# Create scatter plot
scatter_chart = px.scatter(
df,
x='x',
y='y',
height=400)
# Get clicked point from the chart
clicked_point = plotly_events(scatter_chart)
if clicked_point:
x_clicked = clicked_point[0]['x']
y_clicked = clicked_point[0]['y']
# Find nearest neighbor
X = df[['x', 'y']].values
nbrs = NearestNeighbors(n_neighbors=1).fit(X)
distances, indices = nbrs.kneighbors([[x_clicked, y_clicked]])
nearest_point = df.iloc[indices[0][0]]
# Display results
col1, col2 = st.columns(2)
with col1:
st.write("Clicked Point:")
st.write(f"X: {x_clicked:.2f}")
st.write(f"Y: {y_clicked:.2f}")
with col2:
st.write("Nearest Point in Dataset:")
st.write(f"X: {nearest_point['x']:.2f}")
st.write(f"Y: {nearest_point['y']:.2f}")
# Display the image
st.write("Associated Image:")
st.image(nearest_point['image_url'])
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?