Py.Cafe

stichbury/

vizro-book-reading-insights

Interactive Book Reading Insights

DocsPricing
  • app.py
  • filtered_books.csv
  • requirements.txt
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""
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()