Py.Cafe

Sindhup24/

altair-interactive-line-chart

Altair Interactive Line Chart for CSV Data

DocsPricing
  • app.py
  • requirements.txt
  • test_longtable_line.csv
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import pandas as pd
import solara
import altair as alt
from vega_datasets import data as vega_data

# Load the CSV file
file_path = 'test_longtable_line.csv'
data = pd.read_csv(file_path)

# Convert date column to datetime
data['date'] = pd.to_datetime(data['date'])

# Extract unique IDs from CSV
unique_ids = data['Id'].unique().tolist()

# Reactive variables
selected_id = solara.reactive(unique_ids[0])
selected_name = solara.reactive(None)
generate_trigger = solara.reactive(0)

# Function to generate line chart using Altair
def plot_line_chart(df, selected_id, selected_name):
    filtered_data = df[(df['Id'] == selected_id) & (df['Name'] == selected_name)]
    if filtered_data.empty:
        print("No data available for the selected Id and Name.")
        return None

    # Create the line chart
    lines = alt.Chart(filtered_data).mark_line().encode(
        x=alt.X('date:T', title='Date'),
        y=alt.Y('value:Q', title='Value', scale=alt.Scale(domain=(0, 30), nice=False), axis=alt.Axis(values=list(range(0, 31)))),
        color=alt.value('steelblue'),
        tooltip=[
            alt.Tooltip('date:T', title='Date'),
            alt.Tooltip('value:Q', title='Value')
        ]
    ).properties(
        width=800,  
        height=400
    )

    # Add points for better tooltip visibility
    points = lines.mark_point().encode(
        tooltip=[
            alt.Tooltip('date:T', title='Date'),
            alt.Tooltip('value:Q', title='Value')
        ]
    )

    # Define the horizontal overlay lines with explicit colors and legend
    thresholds = pd.DataFrame({
        'value': [16, 22, 28],
        'label': ['Threshold 1', 'Threshold 2', 'Threshold 3'],
        'color': ['cyan', 'magenta', 'red']
    })

    yrules = alt.Chart(thresholds).mark_rule().encode(
        y='value:Q',
        color=alt.Color('label:N', scale=alt.Scale(domain=['Threshold 1', 'Threshold 2', 'Threshold 3'], range=['cyan', 'magenta', 'red']), legend=alt.Legend(title="Thresholds")),
        size=alt.value(2),
        strokeDash=alt.condition(
            alt.datum.label == 'Threshold 2',
            alt.value([5, 5]),
            alt.value([1])
        ),
        tooltip=[alt.Tooltip('value:Q', title='Threshold')]
    )

    # Create a layered chart
    layer_chart = alt.layer(lines, points, yrules).resolve_scale(
        y='shared'
    )

    return layer_chart

# Components
@solara.component
def View():
    if generate_trigger.value > 0 and selected_id.value and selected_name.value:
        chart = plot_line_chart(data, selected_id.value, selected_name.value)
        if chart:
            with solara.VBox() as main:
                solara.FigureAltair(chart)
            solara.Info("Chart has been updated.")
        else:
            solara.Warning("No data available for the selected Id and Name.")
    else:
        solara.Warning("Please select an Id and Name.")

@solara.component
def Controls():
    # Filter the names based on the selected Id
    filtered_names = data[data['Id'] == selected_id.value]['Name'].unique().tolist()
    if selected_name.value not in filtered_names:
        selected_name.value = filtered_names[0] if filtered_names else None

    solara.Select('Id', values=unique_ids, value=selected_id)
    solara.Select('Name', values=filtered_names, value=selected_name)
    
    def generate_chart():
        print(f"Generating chart for Id: {selected_id.value}, Name: {selected_name.value}")
        generate_trigger.value += 1

    solara.Button(label="Generate Chart", on_click=generate_chart, icon_name="mdi-chart-line")

@solara.component
def Page():
    with solara.Sidebar():
        Controls()
    View()

# Display the page
Page()