Skip to content

Fix spurious printing of forecast objects during := by leveraging data.table 1.17.0 fix #1161

@nikosbosse

Description

@nikosbosse

CLAUDE:

Summary

Issue #935 reported that forecast objects print their entire contents when columns are modified via :=. This is still reproducible on the current main branch despite workarounds added in #884.

Root cause

This is caused by a known data.table bug (Rdatatable/data.table#3029) where := triggers autoprinting for S3 subclasses of data.table that define custom print methods. The bug was fixed in data.table 1.17.0 via PR #6631.

However, even with data.table >= 1.17.0, the issue persists in scoringutils because of two interacting problems:

1. [.forecast wraps [.data.table and breaks autoprint suppression

The custom [.forecast method (added in #884) wraps [.data.table via NextMethod() and adds validation logic. This wrapping disrupts data.table's internal autoprint suppression mechanism. The method includes a self-described "hack" that skips validation for objects with ≤30 rows to work around print.data.table's internal subsetting, but this doesn't prevent the autoprint itself.

2. print.forecast outputs before calling NextMethod()

print.forecast prints a header (forecast type, forecast unit) before calling NextMethod() to dispatch to print.data.table. The data.table 1.17.0 fix correctly suppresses print.data.table's output during := autoprint, but print.forecast's header output has already been emitted by that point.

Reproducer

library(scoringutils)

ex <- data.table::copy(example_quantile)
cat("BEFORE\n")
ex[, model := paste(model, "a")]
cat("AFTER\n")
# Entire forecast object is printed between BEFORE and AFTER

Proposed fix

  1. Bump data.table dependency from >= 1.16.0 to >= 1.17.0 in DESCRIPTION
  2. Use shouldPrint() in print.forecast: Call data.table's internal shouldPrint(x) at the top of print.forecast() and return invisible(x) early if it returns FALSE. This ensures the forecast header is also suppressed during := autoprint, just as print.data.table suppresses the table content.
  3. Remove the [.forecast hack: The 30-row threshold workaround in [.forecast was added specifically to avoid triggering validation during print.data.table's internal subsetting. With shouldPrint() handling the autoprint suppression, this hack is no longer needed.
  4. Keep [<-.forecast, $<-.forecast, [[<-.forecast: These assignment methods serve a separate purpose (validation on modification) and are unrelated to the printing issue.

Verification

Tested locally with data.table 1.18.2.1. After applying the proposed fix:

  • := operations on forecast objects produce no output (correct)
  • Explicit print() calls still display the full forecast header + table (correct)

Relates to #935.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions