"""
Create a dashboard with 3 pages.
On the first page, plot a chart with the title "Sequence of reading" . It is a scatter chart.
Use the x axis to show the date a book was read. Plot it at y=1.
On the second page, plot a chart with the title "Pages and Book totals" . It shows the cumulative total number of pages read by summing the Number of Pages of each book read in each year, using the Date Read data. Plot date on the x axis and the number of pages on the y axis using a scale on the left hand side of the chart.
Add a filter so the user can change the x axis to adjust the range of dates by year on the x axis.
Superimpose a bar chart showing the total books read for each year, taking data from the Date Read column.
Show the total books read using the right hand side of the chart which can be a different scale to the y axis shown on the left hand side.
On the third page, plot a chart with the title "Ratings over the years".
Eliminate any book where My Rating is 0. Then, for each row of the dataset, plot the My Rating and Average Rating
data points using circles that are connected by a line to show the gap between the two points.
Stack the books vertically on the y axis, ordered alphabetically by Title, and use the x axis to show the rating between 0 and 5. Label each with the Title and Author.
"""
############ Imports ##############
from vizro import Vizro
import vizro.models as vm
from vizro.models.types import capture
import pandas as pd
import plotly.graph_objects as go
from vizro.models.types import capture
####### Function definitions ######
@capture("graph")
def pages_and_book_totals(data_frame):
# Convert 'Date Read' to datetime
data_frame["Date Read"] = pd.to_datetime(data_frame["Date Read"])
# Extract year from 'Date Read'
data_frame["Year Read"] = data_frame["Date Read"].dt.year
# Group by 'Year Read' and calculate cumulative sum of 'Number of Pages'
pages_per_year = data_frame.groupby("Year Read")["Number of Pages"].sum().cumsum()
# Count total books read per year
books_per_year = data_frame.groupby("Year Read").size()
# Create figure
fig = go.Figure()
# Add cumulative pages line
fig.add_trace(
go.Scatter(
x=pages_per_year.index,
y=pages_per_year,
mode="lines",
name="Cumulative Pages",
yaxis="y1",
)
)
# Add total books bar
fig.add_trace(
go.Bar(
x=books_per_year.index,
y=books_per_year,
name="Total Books",
yaxis="y2",
opacity=0.6,
)
)
# Update layout for dual y-axis
fig.update_layout(
title="Pages and Book Totals",
xaxis=dict(title="Year"),
yaxis=dict(title="Cumulative Number of Pages", side="left"),
yaxis2=dict(title="Total Books Read", overlaying="y", side="right"),
barmode="overlay",
)
return fig
@capture("graph")
def sequence_of_reading(data_frame):
# Convert 'Date Read' to datetime
data_frame["Date Read"] = pd.to_datetime(data_frame["Date Read"])
# Create a scatter plot
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=data_frame["Date Read"],
y=[1] * len(data_frame),
mode="markers",
marker=dict(size=10),
name="Books Read",
)
)
# Update layout
fig.update_layout(
title="Sequence of Reading",
xaxis_title="Date Read",
yaxis_title="",
yaxis=dict(showticklabels=False),
showlegend=False,
)
return fig
########### Model code ############
df = pd.read_csv('filtered_books.csv')
df["Date Read"] = pd.to_datetime(df['Date Read'],dayfirst=True)
model = vm.Dashboard(
pages=[
vm.Page(
components=[
vm.Graph(
id="sequence_of_reading",
figure=sequence_of_reading(df),
)
],
title="Sequence of Reading",
layout=vm.Layout(grid=[[0]]),
controls=[],
),
vm.Page(
components=[
vm.Graph(
id="pages_and_book_totals",
figure=pages_and_book_totals(df),
)
],
title="Pages and Book Totals",
layout=vm.Layout(grid=[[0]]),
controls=[
vm.Filter(
column="Year Published",
targets=["pages_and_book_totals"],
selector=vm.RangeSlider(type="range_slider"),
)
],
),
vm.Page(
components=[
vm.Card(
id="ratings_over_the_years",
text="Failed to build component: ratings_over_the_years",
)
],
title="Ratings Over the Years",
layout=vm.Layout(grid=[[0]]),
controls=[],
),
],
title="Book Reading Dashboard",
)
Vizro().build(model).run()