general10 min read

How to Find Trends in Your Data Automatically

Automatically detect trends, seasonality, and inflection points in your data. Upload a CSV and let AI identify what's changing and why it matters.

By DataStoryBot Team

How to Find Trends in Your Data Automatically

"Revenue is up." That observation takes about three seconds with a line chart. The harder questions — Is growth accelerating or decelerating? Is there a seasonal pattern underneath the growth? Did something structural change in March, or is that just noise? — those take real analysis. And most teams skip them because the analysis takes too long.

Trend detection is one of those problems that sounds simple until you actually try to do it well. A linear regression can tell you the slope, but it can't tell you that the slope changed six months ago, or that your "growth" is actually three months of flat performance bookended by two spikes. Understanding trends requires decomposing time series, identifying structural breaks, separating signal from seasonality, and then — critically — explaining what it all means in plain language.

This article covers how to detect trends automatically using DataStoryBot's API, what happens under the hood, and when you should trust the results versus when you need custom statistical models.

What Makes Trend Detection Hard

A trend is a sustained directional movement in a metric over time. That definition is simple. Detecting trends reliably is not, because real data contains several overlapping patterns:

Linear trends — steady increase or decrease over time. Revenue growing at $50K per month. Easy to detect, easy to misinterpret (is it real growth or inflation?).

Exponential trends — growth that accelerates. User signups doubling every quarter. Looks linear when you're in the middle of it, obvious in retrospect.

Seasonal patterns — recurring cycles tied to calendar periods. Retail sales spike in Q4 every year. If you don't account for seasonality, you'll mistake every December for a "trend."

Cyclical patterns — longer-term waves not tied to calendar. Business cycles, adoption curves, inventory buildups. These need more data history to detect.

Step changes — sudden shifts to a new baseline. A pricing change, a product launch, a pandemic. The metric doesn't trend — it jumps and stays.

Inflection points — moments where the direction or rate of change shifts. Growth slowing, decline reversing, acceleration turning into deceleration. These are usually the most important signals in the data, and the hardest to detect programmatically.

Most trend detection tools handle one or two of these well and ignore the rest. A moving average will smooth out seasonality but obscure step changes. A linear regression will miss inflection points entirely. Proper trend analysis requires multiple techniques working together.

The Traditional Approach: Pandas, SciPy, and Manual Interpretation

Here's what a thorough manual trend analysis looks like in Python:

import pandas as pd
import numpy as np
from scipy import stats
from statsmodels.tsa.seasonal import seasonal_decompose
import ruptures  # for change point detection

df = pd.read_csv("monthly_revenue.csv", parse_dates=["date"])
df = df.sort_values("date").set_index("date")

# Basic linear trend
slope, intercept, r_value, p_value, std_err = stats.linregress(
    range(len(df)), df["revenue"]
)
print(f"Linear trend: ${slope:,.0f}/month (R²={r_value**2:.3f})")

# Seasonal decomposition
decomposition = seasonal_decompose(df["revenue"], period=12, model="additive")
trend_component = decomposition.trend
seasonal_component = decomposition.seasonal
residual = decomposition.resid

# Change point detection
signal = df["revenue"].values
algo = ruptures.Pelt(model="rbf").fit(signal)
change_points = algo.predict(pen=10)
print(f"Detected change points at indices: {change_points}")

# Rolling statistics for acceleration
df["rolling_mean_3m"] = df["revenue"].rolling(3).mean()
df["rolling_mean_6m"] = df["revenue"].rolling(6).mean()
df["acceleration"] = df["rolling_mean_3m"].diff().diff()

That's maybe 30 lines of code, and you still need to interpret the output. What does a change point at index 7 mean in business terms? Is the seasonal component significant enough to matter? Is the acceleration positive or negative, and what's driving it?

The statistical computation is straightforward. The interpretation is where analysts spend most of their time.

The AI Approach: Upload, Analyze, Read

DataStoryBot runs the same kind of statistical analysis — decomposition, regression, change point detection — inside an ephemeral Code Interpreter container. The difference is that it also generates a written narrative explaining what the numbers mean.

Here's the full workflow:

Upload Your Time Series Data

import requests

BASE_URL = "https://datastory.bot/api"

with open("monthly_revenue.csv", "rb") as f:
    upload = requests.post(f"{BASE_URL}/upload", files={"file": f}).json()

container_id = upload["containerId"]
print(f"Columns: {upload['metadata']['columns']}")
print(f"Rows: {upload['metadata']['rowCount']}")

Discover Trend-Focused Story Angles

Use a steering prompt to focus the analysis on trends:

stories = requests.post(f"{BASE_URL}/analyze", json={
    "containerId": container_id,
    "steeringPrompt": "Focus on trends, seasonality, and inflection points in the time series"
}).json()

for story in stories:
    print(f"\n[{story['id']}] {story['title']}")
    print(f"    {story['summary']}")

A typical response for 12 months of revenue data might return:

[1] Growth Stalls in Q3 After Six Months of Acceleration
    Monthly revenue grew at an increasing rate from January through June,
    averaging 8.2% month-over-month growth. Starting in July, growth
    decelerated to 2.1% per month...

[2] Seasonal Pattern Masks Underlying 34% Annual Growth
    After removing a consistent seasonal component (Q1 dip, Q4 spike),
    the underlying trend shows steady 34% annualized growth...

[3] Enterprise Segment Diverges from SMB Starting in April
    When segmented by customer size, enterprise revenue shows a step
    change in April (+40% baseline shift) while SMB revenue follows
    a linear trend...

Each story includes a chartFileId for a preview visualization. Download it to see the trend visually:

for story in stories:
    chart = requests.get(
        f"{BASE_URL}/files/{container_id}/{story['chartFileId']}"
    )
    with open(f"trend_preview_{story['id']}.png", "wb") as f:
        f.write(chart.content)

Generate the Full Trend Analysis

Select the most relevant story and generate the complete report:

report = requests.post(f"{BASE_URL}/refine", json={
    "containerId": container_id,
    "selectedStoryTitle": "Growth Stalls in Q3 After Six Months of Acceleration"
}).json()

# The narrative includes the full trend analysis
print(report["narrative"])

# Charts show the trend decomposition, inflection points, etc.
for chart in report["charts"]:
    print(f"Chart: {chart['caption']}")

# The filtered dataset contains the relevant time series
print(f"Dataset: {report['resultDataset']['fileName']} "
      f"({report['resultDataset']['rowCount']} rows)")

The narrative output is where this approach earns its value. Instead of a slope coefficient and a p-value, you get something like:

Revenue growth decelerated sharply in Q3, dropping from 8.2% to 2.1% month-over-month. The inflection point occurred in late June, coinciding with the end of the promotional pricing period. If the current trajectory holds, Q4 revenue will come in approximately 15% below the Q2 run-rate projection.

That's the kind of insight that takes an analyst 30 minutes to write and a stakeholder 30 seconds to understand.

Steering Prompts for Different Trend Questions

The steeringPrompt parameter in the /api/analyze endpoint lets you focus the trend detection on specific questions:

Year-over-year comparison:

{
  "containerId": "ctr_abc123",
  "steeringPrompt": "Compare year-over-year trends. Identify metrics where this year diverges from last year's pattern."
}

Segment-level trends:

{
  "containerId": "ctr_abc123",
  "steeringPrompt": "Break down trends by the 'region' column. Find segments where trends diverge from the overall direction."
}

Acceleration and deceleration:

{
  "containerId": "ctr_abc123",
  "steeringPrompt": "Focus on rate-of-change analysis. Where is growth accelerating vs decelerating? Identify inflection points."
}

Anomaly-aware trend detection:

{
  "containerId": "ctr_abc123",
  "steeringPrompt": "Identify the underlying trend after removing outliers and anomalous periods. Flag any data points that were excluded."
}

Without a steering prompt, DataStoryBot will still detect trends — it runs a comprehensive statistical profile by default. The steering prompt just prioritizes which patterns make it into the three story angles.

Beyond Trends: Other Patterns DataStoryBot Detects

Trend analysis is one lens. The same upload-analyze-refine pipeline can surface other patterns depending on your data:

Anomaly detection — spikes, drops, and values that don't fit the expected distribution. Useful for operational data where you need to know when something breaks.

Correlation analysis — which columns move together, and which relationships are surprising. Upload a dataset with 20 columns and DataStoryBot will find the non-obvious correlations.

Distribution analysis — how values are spread, whether distributions are normal or skewed, and where clusters form. Particularly useful for customer segmentation data.

Comparative analysis — how groups differ. Upload data with a categorical column and the analysis will compare groups across every numeric dimension.

These aren't separate features — they're different story angles that emerge from the same /api/analyze call depending on what's statistically interesting in your data. Read more about the full analysis capabilities in how to analyze a CSV file with AI.

When AI Trend Detection Works Well

DataStoryBot's trend detection is strongest when:

  • The data is tabular and time-indexed. CSV with a date column and numeric metrics. This is the bread-and-butter case.
  • You need narrative interpretation, not just numbers. If you just need a slope coefficient, use scipy. If you need to explain the trend to a non-technical audience, the narrative output saves significant time.
  • The dataset is exploratory. You don't know what's in the data yet. The three-story-angle approach surfaces patterns you might not have looked for.
  • Speed matters more than customization. A 30-second automated analysis that's 85% right is often more useful than a 3-hour custom analysis that's 95% right — especially for weekly reporting.

When You Need Custom Statistical Models

AI-generated trend analysis has real limitations. Be honest about them:

  • Domain-specific decomposition. If your business has a known seasonal pattern that requires custom decomposition (e.g., academic calendars, fiscal years that don't align with calendar years), a general-purpose model might decompose it incorrectly.
  • Causal inference. DataStoryBot can detect that two metrics changed at the same time. It cannot tell you that one caused the other. For causal analysis, you need experimental design or specialized causal inference frameworks.
  • High-frequency data. Tick-level financial data, sub-second sensor readings, or other high-frequency time series require specialized tools (e.g., ARIMA, Prophet, or custom signal processing). DataStoryBot works best with daily, weekly, or monthly granularity.
  • Regulatory or audit requirements. If you need to document exactly which statistical test was used and reproduce results deterministically, you need version-controlled code with pinned dependencies, not an AI-generated analysis.

The practical approach: use DataStoryBot for exploration and initial reporting, then invest in custom models for the metrics that matter most to your business. The AI analysis often tells you which trends deserve deeper investigation.

Putting It Together: Automated Weekly Trend Reports

Here's a script that uploads the latest data export, finds trends, and saves the report:

import requests
from datetime import date

BASE_URL = "https://datastory.bot/api"

def weekly_trend_report(csv_path, output_dir="./reports"):
    # Upload
    with open(csv_path, "rb") as f:
        upload = requests.post(f"{BASE_URL}/upload", files={"file": f}).json()
    cid = upload["containerId"]

    # Analyze with trend focus
    stories = requests.post(f"{BASE_URL}/analyze", json={
        "containerId": cid,
        "steeringPrompt": "Identify the most significant trends, inflection points, "
                          "and week-over-week changes. Highlight anything that diverges "
                          "from the prior 4-week pattern."
    }).json()

    # Refine the top story
    report = requests.post(f"{BASE_URL}/refine", json={
        "containerId": cid,
        "selectedStoryTitle": stories[0]["title"]
    }).json()

    # Save everything
    today = date.today().isoformat()
    with open(f"{output_dir}/trend_report_{today}.md", "w") as f:
        f.write(report["narrative"])

    for i, chart in enumerate(report["charts"]):
        chart_data = requests.get(
            f"{BASE_URL}/files/{cid}/{chart['fileId']}"
        ).content
        with open(f"{output_dir}/trend_chart_{today}_{i+1}.png", "wb") as f:
            f.write(chart_data)

    ds = report["resultDataset"]
    ds_data = requests.get(f"{BASE_URL}/files/{cid}/{ds['fileId']}").content
    with open(f"{output_dir}/{ds['fileName']}", "wb") as f:
        f.write(ds_data)

    return stories[0]["title"]

title = weekly_trend_report("/data/exports/weekly_metrics.csv")
print(f"Report generated: {title}")

Schedule this with cron or your preferred task runner, and you get a trend report every week that focuses on what actually changed — not a static dashboard that shows the same charts regardless of whether anything interesting happened.

What to Read Next

For a broader look at what DataStoryBot can do with your CSV beyond trend detection, read how to analyze a CSV file with AI.

If you're interested in how the AI interprets and communicates data findings — not just the statistical detection, but the storytelling layer — check out the complete guide to data storytelling with AI.

To understand how DataStoryBot's analysis compares to manual approaches and other tools, see AI-powered data analysis: what it actually does.

Or skip the reading and try it directly — upload a CSV to the DataStoryBot playground and see what trends it finds in your data.

Ready to find your data story?

Upload a CSV and DataStoryBot will uncover the narrative in seconds.

Try DataStoryBot →