Analysis

This analysis compares media coverage of AI-related job losses with coverage of AI-related jobs. The Media Cloud data show weekly story counts from January 1, 2025, through September 4, 2026.

The most noticeable spike occurs in October 2025, when coverage of AI-related jobs rose sharply compared with coverage of AI job losses.

Data source: Media Cloud

Top Sources

The top-source distribution differs noticeably between the two searches, with AI jobs coverage more concentrated in Forbes and AI job-loss coverage distributed more evenly across several outlets.

AI Jobs Source % AI Job Losses Source %
Forbes 23.970% Breitbart 9.756%
Business Insider 9.434% Fortune 9.756%
Fortune 9.101% Forbes 9.451%
Benzinga 8.990% ZDNET 8.537%
CNBC 5.549% Benzinga 6.707%
TechRadar 3.219% The Week 6.402%
Inquirer 2.664% Business Insider 5.488%
Investors.com 2.109% CNBC 3.049%
ZDNET 1.998% Investors.com 3.049%
International Business Times 1.665% TechRadar 2.744%

Code

Here is the R code that was used to create this graph

############################################################
# 1. Load required packages and Media Cloud data
############################################################

library(tidyverse)
library(plotly)

AI_jobs <- read_csv("AI_jobs.csv")
AI_job_losses <- read_csv("AI_job_losses.csv")


############################################################
# 2. Combine the two Media Cloud datasets
############################################################

MediaCloudLong <- bind_rows(
  AI_jobs %>% mutate(Topic = "AI Jobs"),
  AI_job_losses %>% mutate(Topic = "AI Job Losses")
)


############################################################
# 3. Convert dates and create Monday-based weeks
############################################################

MediaCloudLong <- MediaCloudLong %>%
  mutate(
    date = as.Date(date),
    Week = as.Date(
      cut(
        date,
        breaks = "week",
        start.on.monday = TRUE
      )
    )
  )


############################################################
# 4. Aggregate daily story counts into weekly totals
############################################################

MediaCloudWeekly <- MediaCloudLong %>%
  group_by(Week, Topic) %>%
  summarize(
    Stories = sum(count),
    .groups = "drop"
  )


############################################################
# 5. Remove partial beginning and ending weeks
############################################################

MediaCloudWeekly <- MediaCloudWeekly %>%
  filter(
    Week > min(Week),
    Week < max(Week)
  )


############################################################
# 6. Create tooltip information
############################################################

MediaCloudWeekly <- MediaCloudWeekly %>%
  mutate(
    Tooltip = paste0(
      "Topic: ", Topic,
      "<br>Week Beginning: ", format(Week, "%Y-%m-%d"),
      "<br>Stories: ", Stories
    )
  )


############################################################
# 7. Create interactive Plotly line chart
############################################################

Plot <- plot_ly(
  data = MediaCloudWeekly,
  x = ~Week,
  y = ~Stories,
  color = ~Topic,
  colors = c(
    "AI Job Losses" = "black",
    "AI Jobs" = "#6B8E5A"
  ),
  type = "scatter",
  mode = "lines+markers",
  text = ~Tooltip,
  hoverinfo = "text"
) %>%
  layout(
    title = "Weekly Media Coverage: AI Jobs vs. AI Job Losses",
    xaxis = list(
      title = "Week Beginning"
    ),
    yaxis = list(
      title = "Story Count"
    ),
    legend = list(
      title = list(
        text = "Topic"
      )
    ),
    annotations = list(
      list(
        x = as.Date("2025-10-20"),
        y = 51,
        text = "October 2025 spike<br>51 AI Jobs stories",
        showarrow = TRUE,
        arrowhead = 2,
        ax = 70,
        ay = -50
      )
    )
  )


############################################################
# 8. Display chart
############################################################

Plot