Why Migrate?
Farseer offers significant advantages over Prophet while maintaining API compatibility:
- 5-10x faster - Rust-powered performance with automatic multithreading
- Weighted observations - Native support for data quality and recency weighting
- Polars support - Modern DataFrame library for even better performance
- Simpler deployment - Fewer dependencies, single binary distribution
- Same API - Nearly identical interface, minimal learning curve
Quick Migration Guide
❌ Before (Prophet)
from prophet import Prophet
import pandas as pd
df = pd.DataFrame({
'ds': pd.date_range('2020-01-01', periods=100),
'y': range(100)
})
m = Prophet()
m.fit(df)
future = m.make_future_dataframe(periods=30)
forecast = m.predict(future)
✅ After (Farseer)
from farseer import Farseer
import pandas as pd
df = pd.DataFrame({
'ds': pd.date_range('2020-01-01', periods=100),
'y': range(100)
})
m = Farseer() # Just change the class name!
m.fit(df)
future = m.make_future_dataframe(periods=30)
forecast = m.predict(future)
That's it! In most cases, you only need to change Prophet to Farseer.
API Compatibility
Farseer maintains compatibility with Prophet's core API:
✅ Fully Compatible
fit(df)- Train the modelpredict(df)- Make predictionsmake_future_dataframe(periods)- Generate future datesadd_regressor(name, ...)- Add custom regressorsadd_seasonality(name, period, fourier_order)- Add custom seasonalityadd_country_holidays(country)- Add holiday effects- Growth modes:
linear,logistic,flat - Seasonality modes:
additive,multiplicative - Changepoint detection and configuration
⚡ Enhanced Features
- Weighted observations - Add
weightcolumn to your DataFrame - Polars DataFrames - Use Polars for 5-10x better performance
- Automatic multithreading - No configuration needed
Common Migration Scenarios
Scenario 1: Basic Time Series
Prophet
from prophet import Prophet
m = Prophet(
yearly_seasonality=True,
weekly_seasonality=False,
daily_seasonality=False
)
m.fit(df)
forecast = m.predict(future)
Farseer
from farseer import Farseer
m = Farseer(
yearly_seasonality=True,
weekly_seasonality=False,
daily_seasonality=False
)
m.fit(df)
forecast = m.predict(future)
Scenario 2: With Regressors
Prophet
from prophet import Prophet
m = Prophet()
m.add_regressor('temperature')
m.add_regressor('is_weekend')
m.fit(train_df)
forecast = m.predict(test_df)
Farseer
from farseer import Farseer
m = Farseer()
m.add_regressor('temperature')
m.add_regressor('is_weekend')
m.fit(train_df)
forecast = m.predict(test_df)
Scenario 3: With Holidays
Prophet
from prophet import Prophet
m = Prophet()
m.add_country_holidays(country_name='US')
m.fit(df)
forecast = m.predict(future)
Farseer
from farseer import Farseer
m = Farseer()
m.add_country_holidays(country_name='US')
m.fit(df)
forecast = m.predict(future)
Scenario 4: Logistic Growth
Prophet
from prophet import Prophet
df['cap'] = 200 # Carrying capacity
m = Prophet(growth='logistic')
m.fit(df)
future = m.make_future_dataframe(periods=30)
future['cap'] = 200
forecast = m.predict(future)
Farseer
from farseer import Farseer
df['cap'] = 200 # Carrying capacity
m = Farseer(growth='logistic')
m.fit(df)
future = m.make_future_dataframe(periods=30)
future['cap'] = 200
forecast = m.predict(future)
Performance Boost with Polars
For even better performance, migrate to Polars DataFrames:
With Pandas
import pandas as pd
from farseer import Farseer
df = pd.DataFrame({
'ds': pd.date_range('2020-01-01', periods=1000),
'y': range(1000)
})
m = Farseer()
m.fit(df) # Works but slower
With Polars (5-10x faster!)
import polars as pl
from farseer import Farseer
from datetime import datetime
df = pl.DataFrame({
'ds': pl.date_range(datetime(2020, 1, 1),
periods=1000, interval='1d', eager=True),
'y': range(1000)
})
m = Farseer()
m.fit(df) # Much faster! ⚡
New Features in Farseer
Weighted Observations
This feature is unique to Farseer and not available in Prophet:
import polars as pl
from farseer import Farseer
# Add weights to emphasize recent data
df = pl.DataFrame({
'ds': dates,
'y': values,
'weight': [2.0 if i < 50 else 1.0 for i in range(100)]
})
# Weights are automatically detected!
m = Farseer()
m.fit(df)
Automatic Multithreading
No configuration needed - Farseer automatically uses all available CPU cores:
# Prophet: single-threaded by default
from prophet import Prophet
m = Prophet()
m.fit(large_df) # Slower
# Farseer: automatic multithreading
from farseer import Farseer
m = Farseer()
m.fit(large_df) # Much faster with no extra code!
Conditional Seasonality
Both Prophet and Farseer support conditional seasonality:
Prophet
from prophet import Prophet
m = Prophet()
m.add_seasonality(
name='weekly_weekday',
period=7,
fourier_order=3,
condition_name='is_weekday'
)
df['is_weekday'] = (df['ds'].dt.weekday < 5)
m.fit(df)
Farseer (identical!)
from farseer import Farseer
m = Farseer()
m.add_seasonality(
name='weekly_weekday',
period=7,
fourier_order=3,
condition_name='is_weekday'
)
df['is_weekday'] = (df['ds'].dt.weekday < 5)
m.fit(df)
Floor Parameter (Logistic Growth)
Both support floor parameter for saturating minimum:
Prophet
from prophet import Prophet
df['floor'] = 1.5
df['cap'] = 10.0
m = Prophet(growth='logistic')
m.fit(df)
future['floor'] = 1.5
future['cap'] = 10.0
forecast = m.predict(future)
Farseer (identical!)
from farseer import Farseer
df['floor'] = 1.5
df['cap'] = 10.0
m = Farseer(growth='logistic')
m.fit(df)
future['floor'] = 1.5
future['cap'] = 10.0
forecast = m.predict(future)
Smart Regressor Standardization
Farseer auto-detects binary vs continuous regressors:
Prophet
from prophet import Prophet
m = Prophet()
# Manual standardization control
m.add_regressor('is_weekend', standardize=False)
m.add_regressor('temperature', standardize=True)
m.fit(df)
Farseer (smarter!)
from farseer import Farseer
m = Farseer()
# Auto mode detects binary (0/1) vs continuous
m.add_regressor('is_weekend', standardize='auto')
m.add_regressor('temperature', standardize='auto')
# Binary won't be standardized, continuous will be!
m.fit(df)
Independent Holiday Priors
Both support per-holiday prior scales:
Prophet
from prophet import Prophet
m = Prophet()
m.add_country_holidays(
'US',
prior_scale=10.0
)
# Can customize per holiday with holidays DataFrame
m.fit(df)
Farseer
from farseer import Farseer
m = Farseer()
# Independent prior scales per holiday
m.add_holidays(
'christmas',
dates=[...],
prior_scale=20.0 # Strong effect
)
m.add_holidays(
'minor_event',
dates=[...],
prior_scale=5.0 # Weak effect
)
m.fit(df)
Feature Comparison Table
| Feature | Prophet | Farseer |
|---|---|---|
| Basic Forecasting | ✅ Supported | ✅ Supported |
| Linear/Logistic/Flat Growth | ✅ Supported | ✅ Supported |
| Custom Seasonality | ✅ Supported | ✅ Supported |
| Conditional Seasonality | ✅ Supported | ✅ Supported |
| Floor Parameter | ✅ Supported | ✅ Supported |
| Regressors | ✅ Supported | ✅ Supported |
| Auto Regressor Standardization | ❌ Manual only | ✅ 'auto' mode |
| Weighted Observations | ❌ Not supported | ✅ Native support |
| Holidays | ✅ Supported | ✅ Supported |
| Independent Holiday Priors | ✅ Supported | ✅ Supported |
| Multithreading | ❌ Single-threaded | ✅ Automatic |
| Polars DataFrames | ❌ Pandas only | ✅ Polars + Pandas |
| Model Serialization | ✅ JSON/Pickle | ✅ JSON |
| Uncertainty Intervals | ✅ Full posterior (MCMC) | ✅ Approximation (MAP) |
| Performance | ⚠️ Slower | ✅ 5-10x faster |
Troubleshooting
Import Errors
# If you get import errors, ensure Farseer is installed
pip install farseer
# For development version
git clone https://github.com/ryanbieber/seer
cd seer
export PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 # Python 3.13+
maturin develop --release
Minor Differences
While Farseer aims for full Prophet compatibility, there may be minor numerical differences due to:
- Different optimization algorithms (both use L-BFGS but with different implementations)
- Floating point precision differences between Rust and Python
- Random number generation in uncertainty intervals
These differences are typically negligible and don't affect forecast quality.
Need Help?
If you encounter issues migrating from Prophet to Farseer: