> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synthefy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Data enrichment for forecasting

> Learn how to enhance your datasets by integrating valuable insights from trusted external data sources, improving accuracy, depth, and decision-making potential.

## Why Data Enrichment for Forecasting?

Forecasting models often rely heavily on historical internal data — sales, production, demand, etc. However, real-world outcomes are influenced by many external factors such as weather, economic conditions, or regional events.

**Data enrichment** enhances forecasting accuracy by integrating these contextual signals from trusted external data providers. This broader view helps your models:

* Capture hidden relationships and causal effects (e.g., weather affecting retail sales)
* Improve predictive accuracy and robustness
* Enable more informed decision-making

By combining internal and external data, you create a more complete, dynamic foundation for your forecasts.

## Get started

Install the Synthefy Python package:

```bash theme={null}
pip install synthefy
```

Set your API key as an environment variable (you can get your key here: [https://console.synthefy.com/api-keys](https://console.synthefy.com/api-keys)):

```bash theme={null}
export SYNTHEFY_API_KEY="your-api-key-here"
```

## Weather Data

Weather conditions can significantly impact business outcomes such as sales, logistics, or energy consumption. Synthefy’s weather enrichment feature allows you to pull relevant meteorological data directly into your forecasting pipeline.

### How to Fetch Weather Data from Our API

The example below demonstrates how to retrieve daily temperature, humidity, precipitation, and wind speed data for a given location and time period.

```python theme={null}
from synthefy.api_client import SynthefyAPIClient
from synthefy.synthefy_helpers import get_weather_data

client = SynthefyAPIClient()

weather_df = get_weather_data(
    client=client,
    location_name="Springfield",
    weather_parameters="basic",  # temperature, humidity, precip, wind_speed
    start_time="2012-10-01T00:00:00",
    end_time="2012-10-26T23:59:59",
    auto_select_location=True,  # Skip interactive selection for demo
)

print(weather_df.head())
```

<div
  style={{
width: "min(900px, 100%)",
margin: "2rem auto",
display: "grid",
gridTemplateColumns: "repeat(4, 1fr)",
border: "1px solid #f5b75b",
borderRadius: "10px",
overflow: "hidden",
boxShadow: "0 4px 12px rgba(0,0,0,0.05)",
fontFamily: "Inter, sans-serif",
}}
>
  {["timestamp", "temperature (°C)", "humidity (%)", "pressure (hPa)"].map(
      (h) => (
        <div
          key={h}
          style={{
            padding: "14px 10px",
            fontWeight: 600,
            background: "linear-gradient(90deg, #f9a826, #f7941d)",
            color: "#fff",
            textAlign: "center",
            fontSize: "0.95rem",
            letterSpacing: "0.3px",
          }}
        >
          {h}
        </div>
      )
    )}

  {[
      ["2012-10-01", 19, 84, 1023],
      ["2012-10-02", 22, 73, 1027],
      ["2012-10-03", 24, 77, 1025],
      ["2012-10-04", 29, 72, 1022],
      ["2012-10-05", 32, 61, 1020],
    ].map((row, i) =>
      row.map((val, j) => (
        <div
          key={`${i}-${j}`}
          style={{
            padding: "12px 8px",
            textAlign: "center",
            background: i % 2 === 0 ? "#ffffff" : "#fafafa",
            borderBottom: i === 4 ? "none" : "1px solid #eee",
            fontSize: "0.9rem",
            color: "#333",
          }}
        >
          {val}
        </div>
      ))
    )}
</div>

## Enrich Your Data with Weather

Once weather data is available, you can merge it with your internal dataset (e.g., store-level sales). This enrichment creates a richer feature set for forecasting, capturing the environmental conditions that may influence your metrics.

```python theme={null}
from synthefy.api_client import SynthefyAPIClient
from synthefy.synthefy_helpers import get_weather_data

client = SynthefyAPIClient()

walmart_sample = df.head(10)  # Small sample for demo

enriched_df = get_weather_data(
    client=client,
    location_name="Springfield",
    weather_parameters="comprehensive",
    user_dataframe=walmart_sample,
    user_timestamp_column="Date",
    auto_select_location=True,  # Skip interactive selection for demo
)

print(forecast_results["forecast"][["Weekly_Sales", "timestamp"]])
```

<div style={{ width: "100%" }}>
  <div
    style={{
  width: "min(1200px, 100%)",
  margin: "2rem auto",
  border: "1px solid #f5b75b",
  borderRadius: "10px",
  boxShadow: "0 4px 12px rgba(0,0,0,0.05)",
  fontFamily: "Inter, sans-serif",
  background: "#fff",
  overflow: "visible", // <-- don't clip the scroller
}}
  >
    {/* Horizontal scroller */}

    <div
      style={{
    overflowX: "auto",
    overflowY: "hidden",
    WebkitOverflowScrolling: "touch",
    overscrollBehaviorX: "contain",
    touchAction: "pan-x",
    borderRadius: "10px", // keep rounded corners on the content
  }}
    >
      {/* Grid */}

      <div
        style={{
      display: "grid",
      gridTemplateColumns: "repeat(14, 140px)", // adjust width per column here
      width: "max-content", // <-- ensures total grid is wider than the card
    }}
      >
        {/* Header (your gradient) */}

        {[
                        "Store","Date","Weekly_Sales","Holiday_Flag","Temperature","Fuel_Price",
                        "CPI","Unemployment","temperature","wind_speed","precip","humidity",
                        "visibility","pressure",
                      ].map((h) => (
                        <div
                          key={h}
                          style={{
                            padding: "14px 10px",
                            fontWeight: 600,
                            background: "linear-gradient(90deg, #f9a826, #f7941d)", // <-- your theme
                            color: "#fff",
                            textAlign: "center",
                            fontSize: "0.9rem",
                            letterSpacing: "0.3px",
                            whiteSpace: "nowrap",
                          }}
                        >
                          {h}
                        </div>
                      ))}

        {/* Rows */}

        {[
                        ["store_1","2010-02-05","1,643,690.90",0,42.31,2.572,211.096358,8.106,29,8,0.4,82,8,1011],
                        ["store_1","2010-02-12","1,641,957.44",1,38.51,2.548,211.24217,8.106,30,7,0.0,81,7,1014],
                        ["store_1","2010-02-19","1,611,968.17",0,39.93,2.514,211.289143,8.106,25,12,0.0,82,10,1019],
                        ["store_1","2010-02-26","1,409,727.59",0,46.63,2.561,211.319643,8.106,26,12,1.2,85,9,1020],
                        ["store_1","2010-03-05","1,554,806.68",0,46.5,2.625,211.350143,8.106,23,12,1.9,94,7,1011],
                      ].map((row, i) =>
                        row.map((val, j) => (
                          <div
                            key={`${i}-${j}`}
                            style={{
                              padding: "12px 8px",
                              textAlign: j < 2 ? "left" : "center",
                              background: i % 2 === 0 ? "#ffffff" : "#fffaf3", // <-- your row tint
                              borderBottom: i === 4 ? "none" : "1px solid #eee",
                              fontSize: "0.9rem",
                              color: "#333",
                              whiteSpace: "nowrap",
                              overflow: "hidden",
                              textOverflow: "ellipsis",
                            }}
                            title={String(val)}
                          >
                            {val}
                          </div>
                        ))
                      )}
      </div>
    </div>
  </div>
</div>

## Haver Data

Economic indicators often influence consumer demand, investment decisions, and market performance. Integrating Haver Analytics data provides a macroeconomic context for your forecasts — useful for finance, retail, and manufacturing domains.

### Haver Data Search

Use this functionality to search for relevant Haver series (e.g., consumer spending, GDP, or employment rates) by keyword. It helps identify which economic metrics best align with your forecasting objectives.

```python theme={null}
from synthefy.api_client import SynthefyAPIClient
from synthefy.synthefy_helpers import find_haver_data

client = SynthefyAPIClient()

haver_data = find_haver_data(
    client=client,
    prompt="sales consumer spending",
    count=3,
    auto_select=True,  # Auto-select for demo
)

print("✅ Found Haver data!")
print(f"📊 Series: {haver_data.get('name')}@{haver_data.get('database_name')}")
print(f"📝 Description: {haver_data.get('description')}")

```

| Item           | Value                                |
| -------------- | ------------------------------------ |
| ✅ Status       | Found Haver data                     |
| 📊 Series      | `TSSTB@USECON`                       |
| 📝 Description | *Sales: Total Business (SA, Bil.\$)* |

### Fetch Haver Data

After identifying relevant series, you can easily pull historical economic time series into your forecasting pipeline. These data streams allow you to factor in broader economic trends and policy effects.

```python theme={null}
from synthefy.api_client import SynthefyAPIClient
from synthefy.synthefy_helpers import find_haver_data

client = SynthefyAPIClient()

haver_df = get_haver_data(
    client=client,
    search_prompt="unemployment rate",
    start_time="2010-01-01T00:00:00",
    end_time="2013-01-01T00:00:00",
    auto_select=True,
)

print(haver_df.head())

```

<div
  style={{
width: "min(500px, 100%)",
margin: "2rem auto",
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
border: "1px solid #f5b75b",
borderRadius: "10px",
overflow: "hidden",
boxShadow: "0 4px 12px rgba(0,0,0,0.05)",
fontFamily: "Inter, sans-serif",
}}
>
  {["timestamp", "LRLHS25"].map((h) => (
      <div
        key={h}
        style={{
          padding: "14px 10px",
          fontWeight: 600,
          background: "linear-gradient(90deg, #f9a826, #f7941d)",
          color: "#fff",
          textAlign: "center",
          fontSize: "0.95rem",
          letterSpacing: "0.3px",
        }}
      >
        {h}
      </div>
    ))}

  {[
      ["2010-01-01", 15.3],
      ["2010-02-01", 15.8],
      ["2010-03-01", 14.9],
      ["2010-04-01", 14.7],
      ["2010-05-01", 14.6],
    ].map((row, i) =>
      row.map((val, j) => (
        <div
          key={`${i}-${j}`}
          style={{
            padding: "12px 8px",
            textAlign: "center",
            background: i % 2 === 0 ? "#ffffff" : "#fffaf3",
            borderBottom: i === 4 ? "none" : "1px solid #eee",
            fontSize: "0.9rem",
            color: "#333",
          }}
        >
          {val}
        </div>
      ))
    )}
</div>

### Forecast with Enriched Data

Once you’ve enriched your internal dataset with weather and economic features, you can feed the combined data into a forecasting model. This example shows how to generate future sales predictions using enriched time series data.

The enriched dataset improves model performance by providing more signals that influence future outcomes — helping your model “see” beyond past trends.

```python theme={null}
# forecast_with_enriched_df.py
import asyncio
import numpy as np
import pandas as pd

from synthefy.api_client import SynthefyAsyncAPIClient, SynthefyAPIClient
from synthefy.synthefy_helpers import get_weather_data

async def main():
    # Load sample data
    df = pd.read_csv("walmart.csv")
    df["Date"] = pd.to_datetime(df["Date"])
    df = df[df["Store"] == "store_1"]  # Use one store for simplicity

    # Split into history vs. future target
    cutoff_date = '2012-11-02'
    history_df = df[df['Date'] <= cutoff_date].copy()

    future_dates = pd.date_range('2012-11-02', periods=7, freq='D')
    target_df = pd.DataFrame({
        'Date': future_dates,
        'Weekly_Sales': np.nan,  # unknown future target
    })

    # Enrich both frames with weather data
    base_client = SynthefyAPIClient()

    # Step 1: Enrich data with weather
    enriched_history = get_weather_data(
        client=base_client,
        location_name="Springfield",
        weather_parameters="basic",
        user_dataframe=history_df,
        user_timestamp_column="Date",
        auto_select_location=True,
    )

    enriched_target = get_weather_data(
        client=base_client,
        location_name="Springfield",
        weather_parameters="basic",
        user_dataframe=target_df,
        user_timestamp_column="Date",
        auto_select_location=True,
    )

    # Step 2: Get weather column names for covariates
    added_hist = [c for c in enriched_history.columns if c not in history_df.columns]
    added_targ = [c for c in enriched_target.columns if c not in target_df.columns]
    metadata_cols = sorted(list(set(added_hist).intersection(added_targ)))

    # Step 3: Generate forecast with enriched data
    async with SynthefyAsyncAPIClient() as client:
        forecast_dfs = await client.forecast_dfs(
            history_dfs=[enriched_history],
            target_dfs=[enriched_target],
            target_col='Weekly_Sales',
            timestamp_col='Date',
            metadata_cols=metadata_cols,
            leak_cols=[],
            model='Migas-1.0'
        )

    forecast_df = forecast_dfs[0]
    print(forecast_df.head())

# Run
asyncio.run(main())
```

<div
  style={{
width: "min(500px, 100%)",
margin: "2rem auto",
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
border: "1px solid #f5b75b",
borderRadius: "10px",
overflow: "hidden",
boxShadow: "0 4px 12px rgba(0,0,0,0.05)",
fontFamily: "Inter, sans-serif",
}}
>
  {["Weekly_Sales", "timestamp"].map((h) => (
      <div
        key={h}
        style={{
          padding: "14px 10px",
          fontWeight: 600,
          background: "linear-gradient(90deg, #f9a826, #f7941d)",
          color: "#fff",
          textAlign: "center",
          fontSize: "0.95rem",
          letterSpacing: "0.3px",
        }}
      >
        {h}
      </div>
    ))}

  {[
      ["1,539,611.63", "2012-11-02"],
      ["1,595,662.38", "2012-11-09"],
      ["1,539,911.13", "2012-11-16"],
      ["1,466,088.13", "2012-11-23"],
    ].map((row, i) =>
      row.map((val, j) => (
        <div
          key={`${i}-${j}`}
          style={{
            padding: "12px 8px",
            textAlign: "center",
            background: i % 2 === 0 ? "#ffffff" : "#fffaf3",
            borderBottom: i === 3 ? "none" : "1px solid #eee",
            fontSize: "0.9rem",
            color: "#333",
          }}
        >
          {val}
        </div>
      ))
    )}
</div>
