I want to be able to hold down a key to drag and select a section of a datetime pyplot graph and have a button that stores the selected datetime range into a dataframe
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import RectangleSelector
from datetime import datetime, timedelta
# Initialize session state for storing selections
if 'selected_ranges' not in st.session_state:
st.session_state.selected_ranges = pd.DataFrame(columns=['Start Date', 'End Date'])
# Generate sample datetime data
def generate_sample_data():
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
values = np.random.randn(len(dates)).cumsum()
return pd.DataFrame({'Date': dates, 'Value': values})
# Function to handle selection
def line_select_callback(eclick, erelease):
if 'temp_selection' not in st.session_state:
st.session_state.temp_selection = {}
x1, x2 = sorted([eclick.xdata, erelease.xdata])
st.session_state.temp_selection = {
'start': matplotlib_num_to_datetime(x1),
'end': matplotlib_num_to_datetime(x2)
}
# Convert matplotlib date numbers to datetime
def matplotlib_num_to_datetime(x):
return datetime.fromordinal(int(x)) + timedelta(days=x%1)
# Create the main plot
def create_plot(df):
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(df['Date'], df['Value'])
ax.set_title('Interactive Date Range Selector')
ax.set_xlabel('Date')
ax.set_ylabel('Value')
# Add the rectangle selector
rect_selector = RectangleSelector(
ax, line_select_callback,
useblit=True,
button=[1], # Left mouse button only
minspanx=5, # Minimum pixel distance to start selection
spancoords='pixels',
interactive=True
)
return fig
# Main app
st.title('Interactive Date Range Selector')
# Generate or get data
df = generate_sample_data()
# Create and display the plot
fig = create_plot(df)
plot_placeholder = st.pyplot(fig)
# Add button to store selection
if st.button('Store Selected Range'):
if 'temp_selection' in st.session_state and st.session_state.temp_selection:
new_range = pd.DataFrame({
'Start Date': [st.session_state.temp_selection['start']],
'End Date': [st.session_state.temp_selection['end']]
})
st.session_state.selected_ranges = pd.concat([
st.session_state.selected_ranges,
new_range
], ignore_index=True)
st.session_state.temp_selection = {} # Clear the temporary selection
st.rerun()
# Display stored ranges
if not st.session_state.selected_ranges.empty:
st.subheader('Stored Date Ranges')
st.dataframe(st.session_state.selected_ranges)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?