{ "cells": [ { "cell_type": "markdown", "id": "03033b7a-ad2e-435b-9191-1d1929f697c9", "metadata": {}, "source": [ "# Sunshine Hours" ] }, { "cell_type": "code", "execution_count": 1, "id": "525d29b0-46e1-4a02-ab35-f0ca14563d7e", "metadata": { "execution": { "iopub.execute_input": "2025-11-05T13:55:19.109031Z", "iopub.status.busy": "2025-11-05T13:55:19.108943Z", "iopub.status.idle": "2025-11-05T13:55:19.112089Z", "shell.execute_reply": "2025-11-05T13:55:19.111917Z" } }, "outputs": [], "source": [ "from math import pi\n", "\n", "from lets_plot import *" ] }, { "cell_type": "code", "execution_count": 2, "id": "e7b870a4-b38f-40e8-b46a-2870a2b6b6f3", "metadata": { "execution": { "iopub.execute_input": "2025-11-05T13:55:19.113039Z", "iopub.status.busy": "2025-11-05T13:55:19.112964Z", "iopub.status.idle": "2025-11-05T13:55:19.114616Z", "shell.execute_reply": "2025-11-05T13:55:19.114460Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "LetsPlot.setup_html()" ] }, { "cell_type": "code", "execution_count": 3, "id": "95acc6a8-2802-437d-b753-8c3b690dff91", "metadata": { "execution": { "iopub.execute_input": "2025-11-05T13:55:19.115390Z", "iopub.status.busy": "2025-11-05T13:55:19.115327Z", "iopub.status.idle": "2025-11-05T13:55:19.116908Z", "shell.execute_reply": "2025-11-05T13:55:19.116720Z" } }, "outputs": [], "source": [ "shift = 15\n", "target_cities = [\"Barcelona\", \"New York City\", \"Lyon\", \"Paris\", \"Amsterdam\", \"Berlin\"]\n", "angles = {\n", " \"JAN\": -shift, \"FEB\": -30 - shift, \"MAR\": -60 - shift, \"APR\": 90 - shift, \"MAY\": 60 - shift, \"JUN\": 30 - shift,\n", " \"JUL\": -shift, \"AUG\": -30 - shift, \"SEP\": -60 - shift, \"OCT\": 90 - shift, \"NOV\": 60 - shift, \"DEC\": 30 - shift,\n", "}" ] }, { "cell_type": "code", "execution_count": 4, "id": "3cca9346-8e95-4efa-aa69-14177d3737a3", "metadata": { "execution": { "iopub.execute_input": "2025-11-05T13:55:19.117600Z", "iopub.status.busy": "2025-11-05T13:55:19.117532Z", "iopub.status.idle": "2025-11-05T13:55:19.119409Z", "shell.execute_reply": "2025-11-05T13:55:19.119234Z" } }, "outputs": [], "source": [ "def get_data(cities):\n", " import pandas as pd\n", " raw_df = pd.read_csv(\"https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/sunshine_hours.csv\")\n", " filtered_df = raw_df[raw_df[\"City\"].isin(cities)]\n", " df = pd.melt(filtered_df, id_vars=[\"Country\", \"City\"], value_vars=filtered_df.columns[2:-1], \\\n", " var_name=\"Month\", value_name=\"Sunshine hours\")\n", " df[\"Month\"] = df[\"Month\"].str.upper()\n", " df[\"Angle\"] = df[\"Month\"].apply(lambda m: angles[m])\n", " return df.sort_values(by=[\"City\"], key=lambda d: [target_cities.index(v) for i, v in d.items()]).reset_index(drop=True)" ] }, { "cell_type": "code", "execution_count": 5, "id": "2b525db5-451f-4b1c-badf-439e4cf0feb0", "metadata": { "execution": { "iopub.execute_input": "2025-11-05T13:55:19.120180Z", "iopub.status.busy": "2025-11-05T13:55:19.120111Z", "iopub.status.idle": "2025-11-05T13:55:19.448707Z", "shell.execute_reply": "2025-11-05T13:55:19.448403Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(72, 5)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
CountryCityMonthSunshine hoursAngle
0SpainBarcelonaAUG264.0-45
1SpainBarcelonaMAY258.045
2SpainBarcelonaMAR206.0-75
\n", "
" ], "text/plain": [ " Country City Month Sunshine hours Angle\n", "0 Spain Barcelona AUG 264.0 -45\n", "1 Spain Barcelona MAY 258.0 45\n", "2 Spain Barcelona MAR 206.0 -75" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = get_data(target_cities)\n", "print(df.shape)\n", "df.head(3)" ] }, { "cell_type": "code", "execution_count": 6, "id": "bdbd5091-3a72-4aae-8431-b873c1bb8864", "metadata": { "execution": { "iopub.execute_input": "2025-11-05T13:55:19.449991Z", "iopub.status.busy": "2025-11-05T13:55:19.449891Z", "iopub.status.idle": "2025-11-05T13:55:19.485410Z", "shell.execute_reply": "2025-11-05T13:55:19.485214Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "font_family = \"ParaType\"\n", "font_face = 'bold'\n", "background_color = \"#fcf3e4\"\n", "grid_color = \"#ccc2a2\"\n", "\n", "y_breaks = [100, 200]\n", "y_breaks_data = {\n", " \"x\": [\"JAN\"] * len(y_breaks),\n", " \"y\": y_breaks,\n", " \"text\": [str(b) for b in y_breaks],\n", "}\n", "\n", "ggplot(df, aes(as_discrete(\"Month\", levels=list(angles.keys())), \"Sunshine hours\")) + \\\n", " geom_text(aes(\"x\", \"y\", label=\"text\"), data=y_breaks_data, \\\n", " angle=-shift, family=font_family, fontface=font_face, size=6, vjust=0) + \\\n", " geom_bar(stat='identity', color=\"black\", fill=\"#fbc117\", \\\n", " tooltips=layer_tooltips().title(\"@City\").line(\"@Month: @{Sunshine hours}\")) + \\\n", " geom_label(aes(\"Month\", label=\"Month\", angle=\"Angle\"), y=330, \\\n", " family=font_family, fontface=font_face, size=8, \\\n", " label_padding=0, label_r=0, label_size=0, fill=background_color) + \\\n", " facet_wrap(facets=\"City\", order=None) + \\\n", " coord_polar(start=pi*shift/180) + \\\n", " labs(title=\"Comparing Sunshine Hours\", \\\n", " caption=\"Sunshine duration is expressed in (average) hours per month\\n\"\n", " \"Data source: \"\n", " \"\"\n", " \"sunshine hours for cities around the world\"\n", " \"\\n\"\n", " \"Original plot: \"\n", " \"\"\n", " \"Giulia Mezzadri, PhD's Post\"\n", " \"\") + \\\n", " ggsize(1000, 850) + \\\n", " theme(axis='blank', \\\n", " plot_title=element_text(size=32, family=font_family, face=font_face, margin=[20, 20, 30]), \\\n", " plot_caption=element_text(family=font_family, face=font_face), \\\n", " strip_text=element_text(size=20, family=font_family, face=font_face), \\\n", " plot_background=element_rect(fill=background_color), \\\n", " panel_grid=element_line(color=grid_color, size=2))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" } }, "nbformat": 4, "nbformat_minor": 5 }