HKUDS/Vibe-Trading · error · ValueError
label_end_times must be 1-D, got shape {span_ends.shape}
Error message
label_end_times must be 1-D, got shape {span_ends.shape} What it means
When label_end_times is not a pandas Series, _as_label_spans converts it with np.asarray to a 1-D float array of span end positions. Passing a 2-D array (or any higher-dimensional array) breaks the positional correspondence between labels and observations, so it is rejected with the offending shape in the message.
Source
Thrown at agent/src/quantlib/crossvalidation.py:145
Raises:
ValueError: If the input is empty, not 1-D, holds a non-finite value, or
declares a label ending before it starts.
"""
if isinstance(label_end_times, pd.Series):
if label_end_times.empty:
raise ValueError("label_end_times is empty")
starts = label_end_times.index
ends = label_end_times.to_numpy()
# searchsorted on the start index converts label end *times* into label
# end *positions*; the right insertion point minus one keeps a label
# that ends between two observations attached to the earlier one.
positions = np.searchsorted(starts, ends, side="right") - 1
positions = np.clip(positions, np.arange(len(starts)), len(starts) - 1)
span_ends = positions.astype(int)
else:
span_ends = np.asarray(label_end_times, dtype=float)
if span_ends.ndim != 1:
raise ValueError(f"label_end_times must be 1-D, got shape {span_ends.shape}")
if span_ends.size == 0:
raise ValueError("label_end_times is empty")
if not np.isfinite(span_ends).all():
raise ValueError("label_end_times holds a non-finite value")
span_ends = span_ends.astype(int)
if (span_ends < np.arange(span_ends.size)).any():
raise ValueError(
"a label cannot end before the observation it belongs to starts"
)
if n_samples is not None and span_ends.size != n_samples:
raise ValueError(
f"label_end_times has {span_ends.size} entries but the sample has {n_samples}"
)
return span_ends
def _apply_purge_and_embargo(View on GitHub (pinned to 80ffdda44c)
Solutions
- Flatten to 1-D: label_end_times = arr.reshape(-1) or arr.ravel()
- Select a single column from DataFrames: df['label_end'].values
- Verify span_ends.ndim == 1 before calling
Example fix
# before folds = purged_kfold_splits(ends.reshape(-1, 1), n_splits=5) # after folds = purged_kfold_splits(ends.reshape(-1), n_splits=5)
Defensive patterns
Strategy: validation
Validate before calling
ends = np.asarray(label_end_times)
if ends.ndim != 1:
ends = ends.reshape(-1)
folds = purged_kfold_splits(ends, n_splits=5) Type guard
def is_1d_array_like(x) -> bool:
a = np.asarray(x)
return a.ndim == 1 Try / catch
try:
folds = purged_kfold_splits(ends, n_splits=5)
except ValueError as e:
if '1-D' in str(e):
folds = purged_kfold_splits(np.asarray(ends).reshape(-1), n_splits=5)
else:
raise Prevention
- Never pass (n,1) column vectors; flatten after one-hot/scaling steps
- Use df[col].to_numpy() rather than passing the DataFrame itself
- Assert ndim == 1 in test fixtures for CV inputs
When it happens
Trigger: Calling the purged CV entry points with a numpy array of shape (n, 1), (1, n), or a DataFrame (which converts to 2-D) instead of a 1-D array or Series.
Common situations: Column vectors from shape (n,1) produced by .reshape(-1,1) during preprocessing; passing a one-column DataFrame where a Series is expected; batched arrays with a leading batch dimension.
Related errors
- label_end_times holds a non-finite value
- survival_prob must be in (0.0, 1.0], got {survival_prob}
- tenor_years must be strictly positive, got {tenor_years}
- spread_bps must be non-negative, got {spread_bps}
- recovery_rate must be in [0.0, 1.0), got {recovery_rate}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/2d138309edee41fe.
Report an issue: GitHub.