streaming_price_increases_inspection

piotrek / streaming_price_increases_inspection

A local file has been selected for analysis:
"/Users/olunia/Downloads/streaming-price-increases-2021-2026.csv"

Load and inspect this file now.

I'll load the selected CSV and show a quick preview.

</>Load CSV data
import pandas as pd

file_path = "/Users/olunia/Downloads/streaming-price-increases-2021-2026.csv"
df = pd.read_csv(file_path)

print(f"Shape: {df.shape}")
columns = df.columns.tolist()
print(f"Columns ({len(columns)}):", columns if len(columns) <= 100 else columns[:100] + ["..."])

df.head()
Shape: (9, 6)
Columns (6): ['service', 'tier', 'price_2021_03', 'price_2026_09', 'change_usd', 'change_pct']
service tier price_2021_03 price_2026_09 change_usd change_pct
0 Apple TV+ Apple TV+ 4.99 14.99 10.0 200.4
1 Disney+ Premium (ad-free) 7.99 18.99 11.0 137.7
2 Peacock Premium Plus (ad-free) 9.99 19.99 10.0 100.1
3 Hulu No Ads 11.99 18.99 7.0 58.4
4 Netflix Standard 13.99 19.99 6.0 42.9
Thinking

Evaluating code outputs

I see that I've not executed any outputs yet, and I've realized I need to confirm if the DataFrame (df) exists, but I also need to be careful about not repeating myself. It seems like the original code load was done, but there’s no visible output. I should probably print the shape, columns, and head of the DataFrame to see what’s missing. However, it feels repetitive because it involves using the existing DataFrame instead of loading it afresh.

The notebook contains the intended CSV-loading and inspection code, but no executed results are available yet to confirm its dimensions, schema, or preview.

</>Inspect dataframe structure
print(f"Shape: {df.shape}")
columns = df.columns.tolist()
print(f"Columns ({len(columns)}):", columns if len(columns) <= 100 else columns[:100] + ["..."])
df.head()
Shape: (9, 6)
Columns (6): ['service', 'tier', 'price_2021_03', 'price_2026_09', 'change_usd', 'change_pct']
service tier price_2021_03 price_2026_09 change_usd change_pct
0 Apple TV+ Apple TV+ 4.99 14.99 10.0 200.4
1 Disney+ Premium (ad-free) 7.99 18.99 11.0 137.7
2 Peacock Premium Plus (ad-free) 9.99 19.99 10.0 100.1
3 Hulu No Ads 11.99 18.99 7.0 58.4
4 Netflix Standard 13.99 19.99 6.0 42.9

The file contains 9 streaming subscription tiers and 6 fields: service, tier, March 2021 price, September 2026 price, absolute change in USD, and percentage change.

The preview shows substantial price increases across the listed services. Apple TV+ rose from 4.99 USD to 14.99 USD, an increase of 10.00 USD or 200.4%, the largest percentage increase among the rows shown. Disney+ Premium increased by 11.00 USD, from 7.99 USD to 18.99 USD.

interactive plot, showing price increase

Thinking

Creating an Altair chart

I need to make an interactive Altair chart that pulls in all the data. The labels will probably represent the service tier. I’m thinking of using a horizontal bar for the change_usd and including a tooltip for the original values. It might be a good idea to sort the data in descending order. I'll focus on getting the code ready and ensuring it looks good for the user!

This interactive bar chart ranks each subscription tier by its absolute price increase from March 2021 to September 2026.

</>Plot price increases
import altair as alt

plot_data = df.copy()
plot_data["subscription"] = plot_data["service"] + " — " + plot_data["tier"]

chart = (
    alt.Chart(plot_data)
    .mark_bar()
    .encode(
        x=alt.X("change_usd:Q", title="Price increase (USD)"),
        y=alt.Y(
            "subscription:N",
            sort=alt.SortField("change_usd", order="descending"),
            title=None,
        ),
        color=alt.Color(
            "change_pct:Q",
            title="Increase (%)",
            scale=alt.Scale(scheme="orangered"),
        ),
        tooltip=[
            alt.Tooltip("service:N", title="Service"),
            alt.Tooltip("tier:N", title="Tier"),
            alt.Tooltip("price_2021_03:Q", title="March 2021 price", format=".2f"),
            alt.Tooltip("price_2026_09:Q", title="September 2026 price", format=".2f"),
            alt.Tooltip("change_usd:Q", title="Increase (USD)", format=".2f"),
            alt.Tooltip("change_pct:Q", title="Increase (%)", format=".1f"),
        ],
    )
    .properties(
        width="container",
        height=360,
        title="Streaming Subscription Price Increases, 2021–2026",
    )
    .interactive()
)

chart

The interactive chart shows absolute subscription price increases from March 2021 to September 2026, with color indicating the percentage increase. Hovering over a bar reveals the service, tier, starting price, ending price, dollar increase, and percent increase.

From the displayed data, Disney+ Premium has the largest observed increase at 11.00 USD. Apple TV+ and Peacock Premium Plus each rose by 10.00 USD. Apple TV+ has the largest relative increase at 200.4%, rising from 4.99 USD to 14.99 USD.

i want to show for each service previous price as gray dot, and new price as red dot, and line between them, I want to show services names on the left, and on the right the percent increase

Thinking

Charting configurations

I need to create a chart with labels, possibly placing the service/tier on the left y-axis and the increase on the right. I'm considering using Altair to make a layered line chart with y categories and x as the price, showing grey and red dots. The percent labels on the right will need calculated positioning, likely based on the max price. I'll make sure I include the service names on the left y-axis and keep everything well-organized in one code.

This slope-style chart compares each previous price (gray) with the new price (red). The percent increase is labeled on the right.

</>Plot subscription price changes
import altair as alt

plot_data = df.copy()
plot_data["subscription"] = plot_data["service"] + " — " + plot_data["tier"]
plot_data["increase_label"] = plot_data["change_pct"].map(lambda x: f"{x:.1f}%")
label_x = plot_data["price_2026_09"].max() + 1.4

order = plot_data.sort_values("change_pct", ascending=False)["subscription"].tolist()

base = alt.Chart(plot_data).encode(
    y=alt.Y(
        "subscription:N",
        sort=order,
        title=None,
        axis=alt.Axis(labelLimit=260),
    )
)

lines = base.mark_rule(strokeWidth=3, color="#9ca3af").encode(
    x=alt.X("price_2021_03:Q", title="Monthly price (USD)"),
    x2="price_2026_09:Q",
    tooltip=[
        alt.Tooltip("service:N", title="Service"),
        alt.Tooltip("tier:N", title="Tier"),
        alt.Tooltip("price_2021_03:Q", title="Previous price (USD)", format=".2f"),
        alt.Tooltip("price_2026_09:Q", title="New price (USD)", format=".2f"),
        alt.Tooltip("change_usd:Q", title="Increase (USD)", format=".2f"),
        alt.Tooltip("change_pct:Q", title="Increase (%)", format=".1f"),
    ],
)

old_prices = base.mark_point(size=130, color="#6b7280").encode(
    x="price_2021_03:Q"
)

new_prices = base.mark_point(size=130, color="#dc2626").encode(
    x="price_2026_09:Q"
)

percent_labels = base.mark_text(
    align="left",
    dx=8,
    fontWeight="bold",
    color="#b91c1c",
).encode(
    x=alt.value(label_x),
    text="increase_label:N",
)

chart = (
    (lines + old_prices + new_prices + percent_labels)
    .properties(
        width="container",
        height=360,
        title="Streaming Subscription Prices: Previous vs. New",
    )
    .configure_view(stroke=None)
)

chart

LLM provider error: MLJAR returned an empty response for streamed reasoning completion.

static plot, larger titles percent increase over right side of chart

Thinking

Planning data visualization

I need to create a response with only one code snippet, focusing on using Seaborn or Matplotlib for the visualization. I’ll place service names on the left and percentages on the right. It seems like I might need account tier names or subscription levels too. Perhaps I should widen the title and adjust font sizes. Also, I’ll make sure the percentage labels have x offsets and set appropriate x-limits for the chart.

A static dumbbell chart will place service and tier names on the left, with larger typography and percent increases aligned on the right.

</>Plot price changes
import matplotlib.pyplot as plt

plot_data = df.copy()
plot_data["subscription"] = plot_data["service"] + " — " + plot_data["tier"]
plot_data = plot_data.sort_values("change_pct", ascending=False).reset_index(drop=True)

y = range(len(plot_data))
max_price = plot_data["price_2026_09"].max()
label_x = max_price + 2.0

fig, ax = plt.subplots(figsize=(13, 7))

# Connect previous and new monthly prices
for i, row in plot_data.iterrows():
    ax.plot(
        [row["price_2021_03"], row["price_2026_09"]],
        [i, i],
        color="#9ca3af",
        linewidth=3,
        zorder=1,
    )

# Previous and new price markers
ax.scatter(
    plot_data["price_2021_03"], y,
    color="#6b7280", s=110, label="Previous price", zorder=2
)
ax.scatter(
    plot_data["price_2026_09"], y,
    color="#dc2626", s=110, label="New price", zorder=3
)

# Percentage labels on the right
for i, row in plot_data.iterrows():
    ax.text(
        label_x, i, f'{row["change_pct"]:.1f}%',
        va="center", ha="left",
        fontsize=13, fontweight="bold", color="#b91c1c"
    )

ax.set_yticks(list(y))
ax.set_yticklabels(plot_data["subscription"], fontsize=13)
ax.invert_yaxis()
ax.set_xlim(0, label_x + 7)
ax.set_xlabel("Monthly price (USD)", fontsize=14, fontweight="bold")
ax.set_title(
    "Streaming Subscription Prices: Previous vs. New",
    fontsize=20, fontweight="bold", pad=18
)
ax.text(
    label_x, -0.8, "Percent increase",
    ha="left", va="center",
    fontsize=14, fontweight="bold", color="#b91c1c"
)

ax.grid(axis="x", color="#e5e7eb", linewidth=1)
ax.set_axisbelow(True)
ax.spines[["top", "right", "left"]].set_visible(False)
ax.tick_params(axis="y", length=0)
ax.legend(loc="lower right", frameon=False, fontsize=12)

plt.tight_layout()
plt.show()
Notebook output

The static figure uses gray dots for March 2021 prices, red dots for September 2026 prices, and connecting lines to show the change for each subscription. Service and tier labels are placed on the left, while bold red percentage increases are positioned in a dedicated right-side area under “Percent increase.”

The underlying data shows substantial increases among the displayed services: Apple TV+ rises from 4.99 USD to 14.99 USD, a 200.4% increase; Disney+ Premium rises 137.7%; and Peacock Premium Plus rises 100.1%. The ordering by percentage makes these largest relative changes appear at the top.

pimp this plot, better styles, better readability

Thinking

Improving chart code

I need to enhance the code for a chart. It seems the current header might be clipped, so I'll adjust its positioning. Additionally, I want to improve the title and possibly use colors for better visibility. Labeling the years 2021 and 2026 directly could help too. I think I should also ensure the percentage is displayed correctly on the right side. Matplotlib offers refined options, so I'll focus on creating just one clear chart without any dollar signs for currency.

I’ll refine the dumbbell chart with a cleaner hierarchy, softer grid, clearer direct labels, and a separate right-side percentage column.

</>Plot subscription changes
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plot_data = df.copy()
plot_data["subscription"] = plot_data["service"] + " — " + plot_data["tier"]
plot_data = plot_data.sort_values("change_pct", ascending=False).reset_index(drop=True)

old_color = "#64748B"
new_color = "#E45756"
line_color = "#CBD5E1"
text_color = "#172033"
muted_text = "#64748B"

y = list(range(len(plot_data)))
max_price = plot_data["price_2026_09"].max()
percent_x = max_price + 5.0

fig, ax = plt.subplots(figsize=(14, 7.5), facecolor="#FFFFFF")
ax.set_facecolor("#FFFFFF")

# Horizontal connectors
for i, row in plot_data.iterrows():
    ax.hlines(
        y=i,
        xmin=row["price_2021_03"],
        xmax=row["price_2026_09"],
        color=line_color,
        linewidth=5,
        zorder=1,
    )

# Price points
ax.scatter(
    plot_data["price_2021_03"], y,
    s=105, color=old_color, edgecolor="white", linewidth=1.6,
    zorder=3, label="March 2021"
)
ax.scatter(
    plot_data["price_2026_09"], y,
    s=125, color=new_color, edgecolor="white", linewidth=1.6,
    zorder=4, label="September 2026"
)

# Direct price labels and right-side percentage labels
for i, row in plot_data.iterrows():
    ax.annotate(
        f'{row["price_2021_03"]:.2f}',
        (row["price_2021_03"], i),
        xytext=(0, -17), textcoords="offset points",
        ha="center", va="top", fontsize=9.5, color=muted_text
    )
    ax.annotate(
        f'{row["price_2026_09"]:.2f}',
        (row["price_2026_09"], i),
        xytext=(0, 15), textcoords="offset points",
        ha="center", va="bottom", fontsize=9.5, fontweight="bold",
        color=new_color
    )
    ax.text(
        percent_x, i, f'+{row["change_pct"]:.1f}%',
        va="center", ha="right", fontsize=12, fontweight="bold",
        color=new_color
    )

# Axes and labels
ax.set_yticks(y)
ax.set_yticklabels(plot_data["subscription"], fontsize=12, color=text_color)
ax.invert_yaxis()
ax.set_xlim(0, percent_x + 1)
ax.set_ylim(len(plot_data) - 0.4, -1.25)
ax.set_xlabel("Monthly price (USD)", fontsize=12, fontweight="bold", color=text_color, labelpad=12)

ax.text(
    percent_x, -0.82, "PERCENT INCREASE",
    ha="right", va="center", fontsize=10, fontweight="bold", color=muted_text
)

# Styling
ax.xaxis.grid(True, color="#E2E8F0", linewidth=1)
ax.yaxis.grid(False)
ax.set_axisbelow(True)
ax.spines[["top", "right", "left", "bottom"]].set_visible(False)
ax.tick_params(axis="x", length=0, labelsize=10, colors=muted_text)
ax.tick_params(axis="y", length=0, pad=12)

fig.suptitle(
    "Streaming subscription prices have risen sharply since 2021",
    x=0.125, y=0.98, ha="left",
    fontsize=20, fontweight="bold", color=text_color
)
ax.set_title(
    "Monthly prices in USD; subscriptions are ranked by percentage increase",
    loc="left", fontsize=11.5, color=muted_text, pad=24
)

legend_handles = [
    Line2D([0], [0], marker="o", color="none", markerfacecolor=old_color,
           markeredgecolor="white", markeredgewidth=1.3, markersize=9, label="March 2021"),
    Line2D([0], [0], marker="o", color="none", markerfacecolor=new_color,
           markeredgecolor="white", markeredgewidth=1.3, markersize=9, label="September 2026"),
]
ax.legend(
    handles=legend_handles, loc="lower left", bbox_to_anchor=(0, -0.14),
    ncol=2, frameon=False, fontsize=10.5, handletextpad=0.5, columnspacing=1.8
)

plt.subplots_adjust(left=0.28, right=0.94, top=0.82, bottom=0.15)
plt.show()
Notebook output

The latest static dumbbell chart is a clear improvement in readability: it separates the old and new prices with high-contrast markers, uses thicker muted connectors to emphasize change, and ranks subscriptions by percentage increase so the strongest movements are immediately visible.

The typography now has a useful hierarchy: a large descriptive headline, a smaller explanatory subtitle, readable service labels, and direct point labels. The dedicated right-side “PERCENT INCREASE” column avoids forcing readers to estimate changes from the distance between dots. Soft vertical gridlines and removal of unnecessary borders reduce visual clutter, while the legend cleanly explains the two time points.

The design appropriately emphasizes the relative increases while retaining the actual monthly price context in USD.

larger ser vices font, both prices on the same side of line, not one down and one up, instead read in septmeber please make green, green dot, green prices and ghreen price increase

Thinking

Modifying plot labels

I need to provide a modified plot in one block while ensuring the font service is correct. It seems the labels for both prices should be on the same side, likely above the line, to avoid any overlap. I’m thinking of placing both old and new labels above, possibly using offsets to align them left and right. Also, the wording should say “read in September,” and I’ll need to make “September” green. I'll need the specific code for that.

This keeps both price labels above their connectors, increases the service-label font, and makes September prices and percentage increases green.

</>Plot subscription changes
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plot_data = df.copy()
plot_data["subscription"] = plot_data["service"] + " — " + plot_data["tier"]
plot_data = plot_data.sort_values("change_pct", ascending=False).reset_index(drop=True)

old_color = "#64748B"
sept_color = "#16A34A"
line_color = "#CBD5E1"
text_color = "#172033"
muted_text = "#64748B"

y = list(range(len(plot_data)))
max_price = plot_data["price_2026_09"].max()
percent_x = max_price + 5.0

fig, ax = plt.subplots(figsize=(14.5, 7.8), facecolor="white")
ax.set_facecolor("white")

for i, row in plot_data.iterrows():
    ax.hlines(
        y=i,
        xmin=row["price_2021_03"],
        xmax=row["price_2026_09"],
        color=line_color,
        linewidth=5,
        zorder=1,
    )

ax.scatter(
    plot_data["price_2021_03"], y,
    s=105, color=old_color, edgecolor="white", linewidth=1.6,
    zorder=3, label="March 2021"
)
ax.scatter(
    plot_data["price_2026_09"], y,
    s=130, color=sept_color, edgecolor="white", linewidth=1.6,
    zorder=4, label="September 2026"
)

# Keep both prices above the connector line.
for i, row in plot_data.iterrows():
    ax.annotate(
        f'{row["price_2021_03"]:.2f}',
        (row["price_2021_03"], i),
        xytext=(-4, 15), textcoords="offset points",
        ha="right", va="bottom", fontsize=10, color=old_color
    )
    ax.annotate(
        f'{row["price_2026_09"]:.2f}',
        (row["price_2026_09"], i),
        xytext=(4, 15), textcoords="offset points",
        ha="left", va="bottom", fontsize=10, fontweight="bold",
        color=sept_color
    )
    ax.text(
        percent_x, i, f'+{row["change_pct"]:.1f}%',
        va="center", ha="right", fontsize=12, fontweight="bold",
        color=sept_color
    )

ax.set_yticks(y)
ax.set_yticklabels(plot_data["subscription"], fontsize=14, fontweight="medium", color=text_color)
ax.invert_yaxis()
ax.set_xlim(0, percent_x + 1)
ax.set_ylim(len(plot_data) - 0.4, -1.25)
ax.set_xlabel("Monthly price (USD)", fontsize=12, fontweight="bold", color=text_color, labelpad=12)

ax.text(
    percent_x, -0.82, "PERCENT INCREASE",
    ha="right", va="center", fontsize=10, fontweight="bold", color=muted_text
)

ax.xaxis.grid(True, color="#E2E8F0", linewidth=1)
ax.set_axisbelow(True)
ax.spines[["top", "right", "left", "bottom"]].set_visible(False)
ax.tick_params(axis="x", length=0, labelsize=10, colors=muted_text)
ax.tick_params(axis="y", length=0, pad=12)

fig.suptitle(
    "Streaming subscription prices have risen sharply since 2021",
    x=0.125, y=0.98, ha="left",
    fontsize=20, fontweight="bold", color=text_color
)
ax.set_title(
    "Monthly prices in USD; subscriptions are ranked by percentage increase",
    loc="left", fontsize=11.5, color=muted_text, pad=24
)

legend_handles = [
    Line2D([0], [0], marker="o", color="none", markerfacecolor=old_color,
           markeredgecolor="white", markeredgewidth=1.3, markersize=9, label="March 2021"),
    Line2D([0], [0], marker="o", color="none", markerfacecolor=sept_color,
           markeredgecolor="white", markeredgewidth=1.3, markersize=9, label="September 2026"),
]
ax.legend(
    handles=legend_handles, loc="lower left", bbox_to_anchor=(0, -0.14),
    ncol=2, frameon=False, fontsize=10.5, handletextpad=0.5, columnspacing=1.8
)

plt.subplots_adjust(left=0.30, right=0.94, top=0.82, bottom=0.15)
plt.show()
Notebook output

The latest figure applies the requested styling: service labels are larger at 14 pt, and both March 2021 and September 2026 price labels sit above each connector line. September 2026 is consistently green across the dot, bold price label, legend marker, and percentage-increase column. The older March 2021 values remain muted gray, preserving a clear before-versus-after distinction.

The only visible issue is a harmless font fallback warning: Matplotlib replaced medium with its normal 400 weight, so the service labels may look slightly less bold than intended.

Made with MLJAR
Explore more conversationsMore from piotrek