sofiamoncada commited on
Commit
0a20a7b
·
verified ·
1 Parent(s): c7d9f35

Upload Notebook_2_AI_pricing_and_demand_assistant_for_an_online_bookstore (2).ipynb

Browse files
Notebook_2_AI_pricing_and_demand_assistant_for_an_online_bookstore (2).ipynb ADDED
@@ -0,0 +1,685 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": []
7
+ },
8
+ "kernelspec": {
9
+ "name": "python3",
10
+ "display_name": "Python 3"
11
+ },
12
+ "language_info": {
13
+ "name": "python"
14
+ }
15
+ },
16
+ "cells": [
17
+ {
18
+ "cell_type": "code",
19
+ "source": [
20
+ "print(\"RUNNING CLEAN pythonanalysis.ipynb\")"
21
+ ],
22
+ "metadata": {
23
+ "colab": {
24
+ "base_uri": "https://localhost:8080/"
25
+ },
26
+ "id": "SvvHVGkaLNXt",
27
+ "outputId": "164fc247-99d2-463d-a994-b22481a1547f"
28
+ },
29
+ "execution_count": 6,
30
+ "outputs": [
31
+ {
32
+ "output_type": "stream",
33
+ "name": "stdout",
34
+ "text": [
35
+ "RUNNING CLEAN pythonanalysis.ipynb\n"
36
+ ]
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ "cell_type": "code",
42
+ "source": [
43
+ "\n",
44
+ "from pathlib import Path\n",
45
+ "print(list(Path(\"data\").glob(\"*\")))"
46
+ ],
47
+ "metadata": {
48
+ "colab": {
49
+ "base_uri": "https://localhost:8080/"
50
+ },
51
+ "id": "OMloI8HHdXF-",
52
+ "outputId": "2ac478b1-8c54-4e7d-8b4f-5c23bdf72c11"
53
+ },
54
+ "execution_count": 7,
55
+ "outputs": [
56
+ {
57
+ "output_type": "stream",
58
+ "name": "stdout",
59
+ "text": [
60
+ "[]\n"
61
+ ]
62
+ }
63
+ ]
64
+ },
65
+ {
66
+ "cell_type": "code",
67
+ "source": [
68
+ "print(\"RUNNING CLEAN pythonanalysis.ipynb\")\n",
69
+ "\n",
70
+ "import pandas as pd\n",
71
+ "from pathlib import Path\n",
72
+ "\n",
73
+ "DATA_DIR = Path(\"data\")\n",
74
+ "print(\"Files in data folder:\", list(DATA_DIR.glob(\"*\")))\n",
75
+ "\n",
76
+ "books_df = pd.read_csv(DATA_DIR / \"books_real_world.csv\")\n",
77
+ "sales_df = pd.read_csv(DATA_DIR / \"books_sales.csv\")\n",
78
+ "reviews_df = pd.read_csv(DATA_DIR / \"books_reviews.csv\")\n",
79
+ "features_df = pd.read_csv(DATA_DIR / \"books_features.csv\")\n",
80
+ "master_df = pd.read_csv(DATA_DIR / \"books_master.csv\")\n",
81
+ "\n",
82
+ "sales_df[\"date\"] = pd.to_datetime(sales_df[\"date\"], errors=\"coerce\")\n",
83
+ "reviews_df[\"review_date\"] = pd.to_datetime(reviews_df[\"review_date\"], errors=\"coerce\")\n",
84
+ "\n",
85
+ "print(\"Files loaded successfully.\")\n",
86
+ "master_df.head()"
87
+ ],
88
+ "metadata": {
89
+ "colab": {
90
+ "base_uri": "https://localhost:8080/",
91
+ "height": 418
92
+ },
93
+ "id": "U-ihZ7BphbXd",
94
+ "outputId": "6fe7c7d6-1b8a-4360-ec53-bf54f34384f3"
95
+ },
96
+ "execution_count": 10,
97
+ "outputs": [
98
+ {
99
+ "output_type": "stream",
100
+ "name": "stdout",
101
+ "text": [
102
+ "RUNNING CLEAN pythonanalysis.ipynb\n",
103
+ "Files in data folder: []\n"
104
+ ]
105
+ },
106
+ {
107
+ "output_type": "error",
108
+ "ename": "FileNotFoundError",
109
+ "evalue": "[Errno 2] No such file or directory: 'data/books_real_world.csv'",
110
+ "traceback": [
111
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
112
+ "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
113
+ "\u001b[0;32m/tmp/ipykernel_12271/775790723.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Files in data folder:\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mglob\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"*\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mbooks_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m\"books_real_world.csv\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0msales_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m\"books_sales.csv\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mreviews_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m\"books_reviews.csv\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
114
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36mread_csv\u001b[0;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[0m\n\u001b[1;32m 1024\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupdate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkwds_defaults\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1025\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1026\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_read\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilepath_or_buffer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1027\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1028\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
115
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36m_read\u001b[0;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[1;32m 618\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 619\u001b[0m \u001b[0;31m# Create the parser.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 620\u001b[0;31m \u001b[0mparser\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mTextFileReader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilepath_or_buffer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 621\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mchunksize\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0miterator\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
116
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[1;32m 1618\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1619\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhandles\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mIOHandles\u001b[0m \u001b[0;34m|\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1620\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_engine\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_make_engine\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mengine\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1621\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1622\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mclose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
117
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36m_make_engine\u001b[0;34m(self, f, engine)\u001b[0m\n\u001b[1;32m 1878\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m\"b\"\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1879\u001b[0m \u001b[0mmode\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m\"b\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1880\u001b[0;31m self.handles = get_handle(\n\u001b[0m\u001b[1;32m 1881\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1882\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
118
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/common.py\u001b[0m in \u001b[0;36mget_handle\u001b[0;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[1;32m 871\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mioargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mencoding\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m\"b\"\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mioargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 872\u001b[0m \u001b[0;31m# Encoding\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 873\u001b[0;31m handle = open(\n\u001b[0m\u001b[1;32m 874\u001b[0m \u001b[0mhandle\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 875\u001b[0m \u001b[0mioargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
119
+ "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'data/books_real_world.csv'"
120
+ ]
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ "cell_type": "code",
126
+ "source": [
127
+ "import pandas as pd\n",
128
+ "from pathlib import Path\n",
129
+ "\n",
130
+ "DATA_DIR = Path(\"data\")\n",
131
+ "\n",
132
+ "books_df = pd.read_csv(DATA_DIR / \"books_real_world.csv\")\n",
133
+ "sales_df = pd.read_csv(DATA_DIR / \"books_sales.csv\")\n",
134
+ "reviews_df = pd.read_csv(DATA_DIR / \"books_reviews.csv\")\n",
135
+ "features_df = pd.read_csv(DATA_DIR / \"books_features.csv\")\n",
136
+ "master_df = pd.read_csv(DATA_DIR / \"books_master.csv\")\n",
137
+ "\n",
138
+ "sales_df[\"date\"] = pd.to_datetime(sales_df[\"date\"], errors=\"coerce\")\n",
139
+ "reviews_df[\"review_date\"] = pd.to_datetime(reviews_df[\"review_date\"], errors=\"coerce\")\n",
140
+ "\n",
141
+ "print(\"Files loaded successfully.\")\n",
142
+ "master_df.head()"
143
+ ],
144
+ "metadata": {
145
+ "colab": {
146
+ "base_uri": "https://localhost:8080/",
147
+ "height": 382
148
+ },
149
+ "id": "k2WwKFrVdYW-",
150
+ "outputId": "6c4f7de3-5ec6-4115-beab-1e131e642a7c"
151
+ },
152
+ "execution_count": 9,
153
+ "outputs": [
154
+ {
155
+ "output_type": "error",
156
+ "ename": "FileNotFoundError",
157
+ "evalue": "[Errno 2] No such file or directory: 'data/books_real_world.csv'",
158
+ "traceback": [
159
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
160
+ "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
161
+ "\u001b[0;32m/tmp/ipykernel_12271/3373472929.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mDATA_DIR\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPath\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"data\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mbooks_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m\"books_real_world.csv\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0msales_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m\"books_sales.csv\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mreviews_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDATA_DIR\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m\"books_reviews.csv\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
162
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36mread_csv\u001b[0;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[0m\n\u001b[1;32m 1024\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupdate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkwds_defaults\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1025\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1026\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_read\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilepath_or_buffer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1027\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1028\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
163
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36m_read\u001b[0;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[1;32m 618\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 619\u001b[0m \u001b[0;31m# Create the parser.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 620\u001b[0;31m \u001b[0mparser\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mTextFileReader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilepath_or_buffer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 621\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mchunksize\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0miterator\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
164
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[1;32m 1618\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1619\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhandles\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mIOHandles\u001b[0m \u001b[0;34m|\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1620\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_engine\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_make_engine\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mengine\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1621\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1622\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mclose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
165
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/parsers/readers.py\u001b[0m in \u001b[0;36m_make_engine\u001b[0;34m(self, f, engine)\u001b[0m\n\u001b[1;32m 1878\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m\"b\"\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1879\u001b[0m \u001b[0mmode\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m\"b\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1880\u001b[0;31m self.handles = get_handle(\n\u001b[0m\u001b[1;32m 1881\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1882\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
166
+ "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/io/common.py\u001b[0m in \u001b[0;36mget_handle\u001b[0;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[1;32m 871\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mioargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mencoding\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m\"b\"\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mioargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 872\u001b[0m \u001b[0;31m# Encoding\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 873\u001b[0;31m handle = open(\n\u001b[0m\u001b[1;32m 874\u001b[0m \u001b[0mhandle\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 875\u001b[0m \u001b[0mioargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
167
+ "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'data/books_real_world.csv'"
168
+ ]
169
+ }
170
+ ]
171
+ },
172
+ {
173
+ "cell_type": "code",
174
+ "source": [
175
+ "from pathlib import Path\n",
176
+ "\n",
177
+ "BASE_DIR = Path(\".\")\n",
178
+ "ART_DIR = BASE_DIR / \"artifacts\"\n",
179
+ "PY_FIG_DIR = ART_DIR / \"py\" / \"figures\"\n",
180
+ "PY_TAB_DIR = ART_DIR / \"py\" / \"tables\"\n",
181
+ "\n",
182
+ "PY_FIG_DIR.mkdir(parents=True, exist_ok=True)\n",
183
+ "PY_TAB_DIR.mkdir(parents=True, exist_ok=True)\n",
184
+ "\n",
185
+ "print(\"Saving figures to:\", PY_FIG_DIR.resolve())\n",
186
+ "print(\"Saving tables to:\", PY_TAB_DIR.resolve())"
187
+ ],
188
+ "metadata": {
189
+ "id": "KUzI3Lv9NU1R"
190
+ },
191
+ "execution_count": null,
192
+ "outputs": []
193
+ },
194
+ {
195
+ "cell_type": "code",
196
+ "source": [
197
+ "print(\"=== MASTER DATASET INFO ===\")\n",
198
+ "print(master_df.info())\n",
199
+ "\n",
200
+ "print(\"\\n=== MISSING VALUES ===\")\n",
201
+ "print(master_df.isnull().sum())\n",
202
+ "\n",
203
+ "print(\"\\n=== SAMPLE ===\")\n",
204
+ "master_df.head()"
205
+ ],
206
+ "metadata": {
207
+ "id": "JMPXM3xadZq-"
208
+ },
209
+ "execution_count": null,
210
+ "outputs": []
211
+ },
212
+ {
213
+ "cell_type": "code",
214
+ "source": [
215
+ "!pip install vaderSentiment"
216
+ ],
217
+ "metadata": {
218
+ "id": "n1NpS9gBLz5l"
219
+ },
220
+ "execution_count": null,
221
+ "outputs": []
222
+ },
223
+ {
224
+ "cell_type": "code",
225
+ "source": [
226
+ "from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer\n",
227
+ "\n",
228
+ "analyzer = SentimentIntensityAnalyzer()\n",
229
+ "\n",
230
+ "reviews_df[\"sentiment_score\"] = reviews_df[\"review_text\"].apply(\n",
231
+ " lambda x: analyzer.polarity_scores(str(x))[\"compound\"]\n",
232
+ ")\n",
233
+ "\n",
234
+ "def label_sentiment(score):\n",
235
+ " if score > 0.2:\n",
236
+ " return \"positive\"\n",
237
+ " elif score < -0.2:\n",
238
+ " return \"negative\"\n",
239
+ " else:\n",
240
+ " return \"neutral\"\n",
241
+ "\n",
242
+ "reviews_df[\"sentiment_label\"] = reviews_df[\"sentiment_score\"].apply(label_sentiment)\n",
243
+ "\n",
244
+ "reviews_df.head()"
245
+ ],
246
+ "metadata": {
247
+ "id": "-cpX61cddqVd"
248
+ },
249
+ "execution_count": null,
250
+ "outputs": []
251
+ },
252
+ {
253
+ "cell_type": "code",
254
+ "source": [
255
+ "sentiment_summary = reviews_df.groupby(\"book_id\", as_index=False).agg(\n",
256
+ " avg_sentiment_score=(\"sentiment_score\", \"mean\"),\n",
257
+ " positive_review_share=(\"sentiment_label\", lambda x: (x == \"positive\").mean()),\n",
258
+ " negative_review_share=(\"sentiment_label\", lambda x: (x == \"negative\").mean()),\n",
259
+ " neutral_review_share=(\"sentiment_label\", lambda x: (x == \"neutral\").mean())\n",
260
+ ")\n",
261
+ "\n",
262
+ "sentiment_summary.head()"
263
+ ],
264
+ "metadata": {
265
+ "id": "rKoOhBmGdsmF"
266
+ },
267
+ "execution_count": null,
268
+ "outputs": []
269
+ },
270
+ {
271
+ "cell_type": "code",
272
+ "source": [
273
+ "analysis_df = master_df.merge(sentiment_summary, on=\"book_id\", how=\"left\")\n",
274
+ "\n",
275
+ "analysis_df.head()"
276
+ ],
277
+ "metadata": {
278
+ "id": "AG-xSVCDduEl"
279
+ },
280
+ "execution_count": null,
281
+ "outputs": []
282
+ },
283
+ {
284
+ "cell_type": "code",
285
+ "source": [
286
+ "analysis_df.describe()"
287
+ ],
288
+ "metadata": {
289
+ "id": "oSwkiEr_dw5l"
290
+ },
291
+ "execution_count": null,
292
+ "outputs": []
293
+ },
294
+ {
295
+ "cell_type": "code",
296
+ "source": [
297
+ "top_books = analysis_df.sort_values(\"total_revenue\", ascending=False)[\n",
298
+ " [\"title\", \"category\", \"price_gbp\", \"total_units_sold\", \"total_revenue\", \"pricing_action\"]\n",
299
+ "].head(10)\n",
300
+ "\n",
301
+ "top_books"
302
+ ],
303
+ "metadata": {
304
+ "id": "FI5b26FMdzY9"
305
+ },
306
+ "execution_count": null,
307
+ "outputs": []
308
+ },
309
+ {
310
+ "cell_type": "code",
311
+ "source": [
312
+ "import matplotlib.pyplot as plt\n",
313
+ "\n",
314
+ "top_10 = analysis_df.sort_values(\"total_revenue\", ascending=False).head(10)\n",
315
+ "\n",
316
+ "plt.figure(figsize=(10, 6))\n",
317
+ "plt.barh(top_10[\"title\"], top_10[\"total_revenue\"])\n",
318
+ "plt.gca().invert_yaxis()\n",
319
+ "plt.title(\"Top 10 Books by Revenue\")\n",
320
+ "plt.show()"
321
+ ],
322
+ "metadata": {
323
+ "id": "o2bjBD2Ad18t"
324
+ },
325
+ "execution_count": null,
326
+ "outputs": []
327
+ },
328
+ {
329
+ "cell_type": "code",
330
+ "source": [
331
+ "plt.figure(figsize=(10, 6))\n",
332
+ "plt.barh(top_10[\"title\"], top_10[\"total_revenue\"])\n",
333
+ "plt.gca().invert_yaxis()\n",
334
+ "plt.title(\"Top 10 Books by Revenue\")\n",
335
+ "plt.tight_layout()\n",
336
+ "plt.savefig(PY_FIG_DIR / \"top_10_books_by_revenue.png\")\n",
337
+ "plt.show()"
338
+ ],
339
+ "metadata": {
340
+ "id": "9gJaV-L8Nnyy"
341
+ },
342
+ "execution_count": null,
343
+ "outputs": []
344
+ },
345
+ {
346
+ "cell_type": "code",
347
+ "source": [
348
+ "plt.figure(figsize=(8, 5))\n",
349
+ "plt.scatter(analysis_df[\"avg_sentiment_score\"], analysis_df[\"total_revenue\"])\n",
350
+ "plt.title(\"Sentiment vs Revenue\")\n",
351
+ "plt.xlabel(\"Average Sentiment Score\")\n",
352
+ "plt.ylabel(\"Total Revenue\")\n",
353
+ "plt.tight_layout()\n",
354
+ "plt.savefig(PY_FIG_DIR / \"sentiment_vs_revenue.png\")\n",
355
+ "plt.show()"
356
+ ],
357
+ "metadata": {
358
+ "id": "VTERtp3eNxEB"
359
+ },
360
+ "execution_count": null,
361
+ "outputs": []
362
+ },
363
+ {
364
+ "cell_type": "code",
365
+ "source": [
366
+ "plt.figure(figsize=(8, 5))\n",
367
+ "plt.scatter(analysis_df[\"price_gbp\"], analysis_df[\"total_units_sold\"])\n",
368
+ "plt.title(\"Price vs Units Sold\")\n",
369
+ "plt.xlabel(\"Price\")\n",
370
+ "plt.ylabel(\"Units Sold\")\n",
371
+ "plt.show()"
372
+ ],
373
+ "metadata": {
374
+ "id": "-1Mr_Ez0d6m9"
375
+ },
376
+ "execution_count": null,
377
+ "outputs": []
378
+ },
379
+ {
380
+ "cell_type": "code",
381
+ "source": [
382
+ "plt.figure(figsize=(8, 5))\n",
383
+ "plt.scatter(analysis_df[\"avg_sentiment_score\"], analysis_df[\"total_revenue\"])\n",
384
+ "plt.title(\"Sentiment vs Revenue\")\n",
385
+ "plt.xlabel(\"Sentiment Score\")\n",
386
+ "plt.ylabel(\"Revenue\")\n",
387
+ "plt.show()"
388
+ ],
389
+ "metadata": {
390
+ "id": "1ar--sRUd9Jj"
391
+ },
392
+ "execution_count": null,
393
+ "outputs": []
394
+ },
395
+ {
396
+ "cell_type": "code",
397
+ "source": [
398
+ "category_summary = analysis_df.groupby(\"category\", as_index=False).agg(\n",
399
+ " total_revenue=(\"total_revenue\", \"sum\"),\n",
400
+ " avg_review_score=(\"avg_review_score\", \"mean\"),\n",
401
+ " avg_sentiment_score=(\"avg_sentiment_score\", \"mean\")\n",
402
+ ")\n",
403
+ "\n",
404
+ "category_summary"
405
+ ],
406
+ "metadata": {
407
+ "id": "VoggtyqeeAAp"
408
+ },
409
+ "execution_count": null,
410
+ "outputs": []
411
+ },
412
+ {
413
+ "cell_type": "code",
414
+ "source": [
415
+ "category_summary = category_summary.sort_values(\"total_revenue\")\n",
416
+ "\n",
417
+ "plt.figure(figsize=(8, 5))\n",
418
+ "plt.barh(category_summary[\"category\"], category_summary[\"total_revenue\"])\n",
419
+ "plt.title(\"Revenue by Category\")\n",
420
+ "plt.show()"
421
+ ],
422
+ "metadata": {
423
+ "id": "R7wik3_4eCLh"
424
+ },
425
+ "execution_count": null,
426
+ "outputs": []
427
+ },
428
+ {
429
+ "cell_type": "code",
430
+ "source": [
431
+ "from sklearn.preprocessing import LabelEncoder\n",
432
+ "\n",
433
+ "model_df = analysis_df.copy()\n",
434
+ "\n",
435
+ "# Fill missing numeric values\n",
436
+ "for col in model_df.select_dtypes(include=\"number\").columns:\n",
437
+ " model_df[col] = model_df[col].fillna(model_df[col].median())\n",
438
+ "\n",
439
+ "# Encode category\n",
440
+ "encoder = LabelEncoder()\n",
441
+ "model_df[\"category_encoded\"] = encoder.fit_transform(model_df[\"category\"].astype(str))\n",
442
+ "\n",
443
+ "X = model_df[\n",
444
+ " [\n",
445
+ " \"price_gbp\",\n",
446
+ " \"rating\",\n",
447
+ " \"in_stock\",\n",
448
+ " \"supplier_cost\",\n",
449
+ " \"marketing_score\",\n",
450
+ " \"total_units_sold\",\n",
451
+ " \"avg_monthly_units\",\n",
452
+ " \"avg_review_score\",\n",
453
+ " \"review_count\",\n",
454
+ " \"avg_sentiment_score\",\n",
455
+ " \"positive_review_share\",\n",
456
+ " \"negative_review_share\",\n",
457
+ " \"neutral_review_share\",\n",
458
+ " \"category_encoded\"\n",
459
+ " ]\n",
460
+ "]\n",
461
+ "\n",
462
+ "y = model_df[\"pricing_action\"]\n",
463
+ "\n",
464
+ "X.head()"
465
+ ],
466
+ "metadata": {
467
+ "id": "yf3sS8CJeHeq"
468
+ },
469
+ "execution_count": null,
470
+ "outputs": []
471
+ },
472
+ {
473
+ "cell_type": "code",
474
+ "source": [
475
+ "from sklearn.model_selection import train_test_split\n",
476
+ "\n",
477
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
478
+ " X, y, test_size=0.2, random_state=42\n",
479
+ ")"
480
+ ],
481
+ "metadata": {
482
+ "id": "tiYbWpOceKJJ"
483
+ },
484
+ "execution_count": null,
485
+ "outputs": []
486
+ },
487
+ {
488
+ "cell_type": "code",
489
+ "source": [
490
+ "from sklearn.ensemble import RandomForestClassifier\n",
491
+ "from sklearn.metrics import classification_report, accuracy_score\n",
492
+ "\n",
493
+ "clf = RandomForestClassifier(n_estimators=200, random_state=42)\n",
494
+ "clf.fit(X_train, y_train)\n",
495
+ "\n",
496
+ "y_pred = clf.predict(X_test)\n",
497
+ "\n",
498
+ "print(\"Accuracy:\", accuracy_score(y_test, y_pred))\n",
499
+ "print(classification_report(y_test, y_pred))"
500
+ ],
501
+ "metadata": {
502
+ "id": "kxBnZ4IkeNI2"
503
+ },
504
+ "execution_count": null,
505
+ "outputs": []
506
+ },
507
+ {
508
+ "cell_type": "code",
509
+ "source": [
510
+ "importance_df = pd.DataFrame({\n",
511
+ " \"feature\": X.columns,\n",
512
+ " \"importance\": clf.feature_importances_\n",
513
+ "}).sort_values(\"importance\", ascending=False)\n",
514
+ "\n",
515
+ "importance_df"
516
+ ],
517
+ "metadata": {
518
+ "id": "TLeDMMP2eP_F"
519
+ },
520
+ "execution_count": null,
521
+ "outputs": []
522
+ },
523
+ {
524
+ "cell_type": "code",
525
+ "source": [
526
+ "plt.figure(figsize=(10, 6))\n",
527
+ "plt.barh(importance_df[\"feature\"], importance_df[\"importance\"])\n",
528
+ "plt.gca().invert_yaxis()\n",
529
+ "plt.title(\"Feature Importance\")\n",
530
+ "plt.show()"
531
+ ],
532
+ "metadata": {
533
+ "id": "c9HRi0q4eSjO"
534
+ },
535
+ "execution_count": null,
536
+ "outputs": []
537
+ },
538
+ {
539
+ "cell_type": "code",
540
+ "source": [
541
+ "analysis_df[\"predicted_pricing_action\"] = clf.predict(X)\n",
542
+ "\n",
543
+ "analysis_df[[\"title\", \"pricing_action\", \"predicted_pricing_action\"]].head()"
544
+ ],
545
+ "metadata": {
546
+ "id": "DnKFclJ8eVKF"
547
+ },
548
+ "execution_count": null,
549
+ "outputs": []
550
+ },
551
+ {
552
+ "cell_type": "code",
553
+ "source": [
554
+ "best_book = analysis_df.sort_values(\"total_revenue\", ascending=False).iloc[0][\"book_id\"]\n",
555
+ "\n",
556
+ "ts = (\n",
557
+ " sales_df[sales_df[\"book_id\"] == best_book]\n",
558
+ " .groupby(\"date\")[\"revenue\"]\n",
559
+ " .sum()\n",
560
+ ")\n",
561
+ "\n",
562
+ "ts.index = pd.to_datetime(ts.index)\n",
563
+ "ts = ts.asfreq(\"MS\")\n",
564
+ "\n",
565
+ "ts"
566
+ ],
567
+ "metadata": {
568
+ "id": "sFtWYML8eXfd"
569
+ },
570
+ "execution_count": null,
571
+ "outputs": []
572
+ },
573
+ {
574
+ "cell_type": "code",
575
+ "source": [
576
+ "from statsmodels.tsa.arima.model import ARIMA\n",
577
+ "\n",
578
+ "model = ARIMA(ts, order=(1,1,1))\n",
579
+ "model_fit = model.fit()\n",
580
+ "\n",
581
+ "forecast = model_fit.forecast(steps=3)\n",
582
+ "\n",
583
+ "forecast"
584
+ ],
585
+ "metadata": {
586
+ "id": "gwp9i27meafy"
587
+ },
588
+ "execution_count": null,
589
+ "outputs": []
590
+ },
591
+ {
592
+ "cell_type": "code",
593
+ "source": [
594
+ "plt.figure(figsize=(10, 5))\n",
595
+ "plt.plot(ts, label=\"History\")\n",
596
+ "plt.plot(forecast, label=\"Forecast\")\n",
597
+ "plt.legend()\n",
598
+ "plt.title(\"Revenue Forecast\")\n",
599
+ "plt.show()"
600
+ ],
601
+ "metadata": {
602
+ "id": "WhwoskjwedVS"
603
+ },
604
+ "execution_count": null,
605
+ "outputs": []
606
+ },
607
+ {
608
+ "cell_type": "code",
609
+ "source": [
610
+ "def recommend(row):\n",
611
+ " if row[\"avg_sentiment_score\"] > 0.4 and row[\"avg_monthly_units\"] > 60:\n",
612
+ " return \"Increase price\"\n",
613
+ " elif row[\"avg_sentiment_score\"] < 0:\n",
614
+ " return \"Discount\"\n",
615
+ " else:\n",
616
+ " return \"Keep price\"\n",
617
+ "\n",
618
+ "analysis_df[\"recommendation\"] = analysis_df.apply(recommend, axis=1)\n",
619
+ "\n",
620
+ "analysis_df[[\"title\", \"recommendation\"]].head()"
621
+ ],
622
+ "metadata": {
623
+ "id": "W5CQz9uUefy6"
624
+ },
625
+ "execution_count": null,
626
+ "outputs": []
627
+ },
628
+ {
629
+ "cell_type": "code",
630
+ "source": [
631
+ "final_output = analysis_df[\n",
632
+ " [\"book_id\", \"title\", \"category\", \"price_gbp\", \"total_revenue\", \"recommendation\"]\n",
633
+ "]\n",
634
+ "\n",
635
+ "final_output.head()"
636
+ ],
637
+ "metadata": {
638
+ "id": "Wi86eAS7ejBz"
639
+ },
640
+ "execution_count": null,
641
+ "outputs": []
642
+ },
643
+ {
644
+ "cell_type": "code",
645
+ "source": [
646
+ "analysis_df.to_csv(\"analysis_results.csv\", index=False)\n",
647
+ "final_output.to_csv(\"final_recommendations.csv\", index=False)\n",
648
+ "\n",
649
+ "print(\"Saved successfully\")"
650
+ ],
651
+ "metadata": {
652
+ "id": "OwQQ-Pm6emoj"
653
+ },
654
+ "execution_count": null,
655
+ "outputs": []
656
+ },
657
+ {
658
+ "cell_type": "code",
659
+ "source": [
660
+ "final_output.to_csv(\"final_recommendations.csv\", index=False)"
661
+ ],
662
+ "metadata": {
663
+ "id": "B1tXy1n_igCZ"
664
+ },
665
+ "execution_count": null,
666
+ "outputs": []
667
+ },
668
+ {
669
+ "cell_type": "code",
670
+ "source": [
671
+ "analysis_df.to_csv(PY_TAB_DIR / \"book_analysis_full.csv\", index=False)\n",
672
+ "final_output.to_csv(PY_TAB_DIR / \"final_recommendations.csv\", index=False)\n",
673
+ "category_summary.to_csv(PY_TAB_DIR / \"category_summary.csv\", index=False)\n",
674
+ "importance_df.to_csv(PY_TAB_DIR / \"feature_importance.csv\", index=False)\n",
675
+ "\n",
676
+ "print(\"Dashboard tables saved.\")"
677
+ ],
678
+ "metadata": {
679
+ "id": "FwP4V2bENfAv"
680
+ },
681
+ "execution_count": null,
682
+ "outputs": []
683
+ }
684
+ ]
685
+ }