diff --git a/openml/datasets/dataset.py b/openml/datasets/dataset.py index 7e7f61346..c3d4a71c6 100644 --- a/openml/datasets/dataset.py +++ b/openml/datasets/dataset.py @@ -1,6 +1,7 @@ # License: BSD 3-Clause from __future__ import annotations +import contextlib import gzip import logging import os @@ -295,13 +296,6 @@ def id(self) -> int | None: def _get_repr_body_fields(self) -> Sequence[tuple[str, str | int | None]]: """Collect all information to display in the __repr__ body.""" - # Obtain number of features in accordance with lazy loading. - n_features: int | None = None - if self._qualities is not None and self._qualities["NumberOfFeatures"] is not None: - n_features = int(self._qualities["NumberOfFeatures"]) - elif self._features is not None: - n_features = len(self._features) - fields: dict[str, int | str | None] = { "Name": self.name, "Version": self.version, @@ -312,14 +306,23 @@ def _get_repr_body_fields(self) -> Sequence[tuple[str, str | int | None]]: "Pickle file": ( str(self.data_pickle_file) if self.data_pickle_file is not None else None ), - "# of features": n_features, } + + # We don't consider these fields critical to display, so we use the internal + # attribute to avoid downloading extra files just to generate the repr. + try: + fields["# of features"] = int(self._qualities["NumberOfFeatures"]) # type: ignore[index] + except (TypeError, KeyError, ValueError): + if self._features is not None: + fields["# of features"] = len(self._features) + + with contextlib.suppress(TypeError, KeyError, ValueError): + fields["# of instances"] = int(self._qualities["NumberOfInstances"]) # type: ignore[index] + if self.upload_date is not None: fields["Upload Date"] = self.upload_date.replace("T", " ") if self.dataset_id is not None: fields["OpenML URL"] = self.openml_url - if self._qualities is not None and self._qualities["NumberOfInstances"] is not None: - fields["# of instances"] = int(self._qualities["NumberOfInstances"]) # determines the order in which the information will be printed order = [ @@ -722,7 +725,7 @@ def valid_category(cat: Any) -> bool: raw_cat = pd.Categorical(col, ordered=True, categories=filtered_categories) return pd.Series(raw_cat, index=series.index, name=series.name) - def get_data( # noqa: C901 + def get_data( # noqa: C901, PLR0912 self, target: list[str] | str | None = None, include_row_id: bool = False, # noqa: FBT002 @@ -794,6 +797,22 @@ def get_data( # noqa: C901 ) target_name = target_names[0] + available_columns = list(data.columns) + if target_name in to_exclude: + msg = ( + f"Target column '{target_name}' was removed because it is listed as a " + f"row_id or ignore attribute. " + f"Available columns after filtering: {available_columns}" + ) + raise ValueError(msg) + + if target_name not in data.columns: + msg = ( + f"Target column '{target_name}' does not exist in this dataset. " + f"Available columns: {available_columns}" + ) + raise ValueError(msg) + x = data.drop(columns=[target_name]) y = data[target_name].squeeze() diff --git a/openml/datasets/functions.py b/openml/datasets/functions.py index 970331cf1..12ad42784 100644 --- a/openml/datasets/functions.py +++ b/openml/datasets/functions.py @@ -612,8 +612,7 @@ def create_dataset( # noqa: C901, PLR0912, PLR0915 # Edit: Found it could also be like ["True", "False"] attributes: list[tuple[str, str | list[str]]] | dict[str, str | list[str]] | Literal["auto"], data: pd.DataFrame | np.ndarray | scipy.sparse.coo_matrix, - # TODO(eddiebergman): Function requires `default_target_attribute` exist but API allows None - default_target_attribute: str, + default_target_attribute: str | None, ignore_attribute: str | list[str] | None, citation: str, row_id_attribute: str | None = None, @@ -657,7 +656,8 @@ def create_dataset( # noqa: C901, PLR0912, PLR0915 passing ``attributes='auto'``. The target feature is indicated as meta-data of the dataset. default_target_attribute : str - The default target attribute, if it exists. + The default target attribute, if it exists. Use ``None`` for unsupervised datasets + (e.g. clustering, anomaly detection) where no natural target column exists. Can have multiple values, comma separated. ignore_attribute : str | list Attributes that should be excluded in modelling,