How to create time-based samples for training/testing in Python for data
Learn how to create time-based samples for training/testing in Python for data — an essential task for time series modeling that prevents data leakage and ensures realistic validation. The technique is useful for forecasting sales, web metrics, or any series where chronological order matters.
Prerequisites
- Python 3.8+ installed
- Packages: pandas, scikit-learn, numpy (install with pip if needed)
- Basic knowledge of pandas and train/test in machine learning
Step 1: Why do temporal splitting instead of shuffle
In temporal data, shuffling can cause data leakage: information from the future enters the training set and inflates the metric. Temporal splitting preserves chronological order — training with older data and testing with more recent data.
Step 2: Minimal data structure
We start with a simple DataFrame that has a date column and a target variable. We ensure the date column is datetime and sort by it.
import pandas as pd
import numpy as np
# Exemplo mínimo
np.random.seed(42)
dates = pd.date_range('2022-01-01', periods=100, freq='D')
value = np.random.randn(100).cumsum() + 50
df = pd.DataFrame({'date': dates, 'value': value})
# Converter e ordenar
df['date'] = pd.to_datetime(df['date'])
df = df.sort_values('date').reset_index(drop=True)
print(df.head())
Step 3: Simple temporal train/test split (holdout)
A common approach is to use a final percentage as test (for example, the last 20%). This is simple and prevents temporal mixing.
# Proporção de teste
test_size = 0.2
n = len(df)
split = int(n * (1 - test_size))
train = df.iloc[:split].reset_index(drop=True)
test = df.iloc[split:].reset_index(drop=True)
print('Train:', train['date'].min(), '->', train['date'].max())
print('Test:', test['date'].min(), '->', test['date'].max())
Step 4: Temporal validation with rolling windows
To evaluate model stability, we use temporal cross-validation (rolling/expanding window). Here we create sequential splits where each fold trains on data up to a point t and tests on a future block.
from sklearn.model_selection import TimeSeriesSplit
# Exemplo com TimeSeriesSplit (k folds)
X = df[['value']].copy() # features fictícias
y = df['value']
tscv = TimeSeriesSplit(n_splits=5)
for i, (train_idx, test_idx) in enumerate(tscv.split(X)):
print(f'Fold {i+1}: train {train_idx[0]}-{train_idx[-1]}, test {test_idx[0]}-{test_idx[-1]}')
Step 5: Walk-forward window and fixed test blocks
If you need to forecast a fixed horizon (e.g. 7 days), create a generator that yields windows where the test has fixed length and the training expands or slides.
def rolling_windows(df, train_size, test_size, step=1):
n = len(df)
start = 0
while True:
train_end = start + train_size
test_end = train_end + test_size
if test_end > n:
break
yield df.iloc[start:train_end].reset_index(drop=True), df.iloc[train_end:test_end].reset_index(drop=True)
start += step
# Exemplo
for i, (tr, te) in enumerate(rolling_windows(df, train_size=60, test_size=7, step=7)):
print(f'Window {i+1}: train {tr.date.min().date()}->{tr.date.max().date()}, test {te.date.min().date()}->{te.date.max().date()}')
Step 6: Avoid leaks with future-based features
When creating features (lags, rolling means) ensure you only use information up to t-1 to predict t. Use shift() in pandas to create lags and avoid functions that aggregate future values.
# Exemplo de lags e média móvel sem data leakage
df['lag_1'] = df['value'].shift(1)
df['rolling_7'] = df['value'].shift(1).rolling(window=7, min_periods=1).mean()
# Remover primeiras linhas com NaN resultantes
df_feat = df.dropna().reset_index(drop=True)
print(df_feat.head())
Check the result
Confirm that training dates are always earlier than testing dates and that training features do not contain future values. Check the sizes of the sets and print a sample of the first rows after creating lags/rolling.
# Verificações rápidas
assert train['date'].max() < test['date'].min(), 'Data leakage: sobreposição temporal!'
print('Tamanhos: ', len(train), len(test))
print(df_feat[['date','value','lag_1','rolling_7']].head())
Conclusion
Splitting time series correctly is critical to avoid data leakage and obtain realistic metrics. Use temporal holdout for simple tests, TimeSeriesSplit for more robust validation, and rolling windows to assess stability over time. Next step: train a simple model (e.g.: RandomForest, XGBoost) using the lags and validate with temporal splits. Tip: always visualize the dates and windows to ensure there was no overlap.