codecov[bot]: # [Codecov](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=h1) Report
> Merging [#683](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=desc) into [develop](https://codecov.io/gh/andersbogsnes/ml_tooling/commit/18e5b480bea980347fde64ccbdb81b00dcc04232?el=desc) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/graphs/tree.svg?width=650&height=150&src=pr&token=ucKtL3BlxO)](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           develop      #683    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files           55        63     +8     
  Lines         1424      1687   +263     
  Branches       166       190    +24     
==========================================
+ Hits          1424      1687   +263     
```


| [Impacted Files](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/ml\_tooling/plots/utils.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvcGxvdHMvdXRpbHMucHk=) | `100.00% <ø> (ø)` | |
| [src/ml\_tooling/transformers/binner.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvdHJhbnNmb3JtZXJzL2Jpbm5lci5weQ==) | `100.00% <ø> (ø)` | |
| [src/ml\_tooling/transformers/feature\_union.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvdHJhbnNmb3JtZXJzL2ZlYXR1cmVfdW5pb24ucHk=) | `100.00% <ø> (ø)` | |
| [src/ml\_tooling/transformers/renamer.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvdHJhbnNmb3JtZXJzL3JlbmFtZXIucHk=) | `100.00% <ø> (ø)` | |
| [src/ml\_tooling/transformers/to\_categorical.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvdHJhbnNmb3JtZXJzL3RvX2NhdGVnb3JpY2FsLnB5) | `100.00% <ø> (ø)` | |
| [src/ml\_tooling/\_\_init\_\_.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvX19pbml0X18ucHk=) | `100.00% <100.00%> (ø)` | |
| [src/ml\_tooling/baseclass.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvYmFzZWNsYXNzLnB5) | `100.00% <100.00%> (ø)` | |
| [src/ml\_tooling/config.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvY29uZmlnLnB5) | `100.00% <100.00%> (ø)` | |
| [src/ml\_tooling/data/\_\_init\_\_.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvZGF0YS9fX2luaXRfXy5weQ==) | `100.00% <100.00%> (ø)` | |
| [src/ml\_tooling/data/base\_data.py](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree#diff-c3JjL21sX3Rvb2xpbmcvZGF0YS9iYXNlX2RhdGEucHk=) | `100.00% <100.00%> (ø)` | |
| ... and [48 more](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=footer). Last update [c7c2012...dd29e7a](https://codecov.io/gh/andersbogsnes/ml_tooling/pull/683?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8310c3d..6b95b1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# v.0.12.1
+- Dataset features can now be easily accessed with the property dataset.features
+
 # v0.12.0
 - Permutation importance and Feature importance are now two different plotting methods.
 - `Model.test_estimators` now takes a `feature_pipeline` argument
diff --git a/src/ml_tooling/data/base_data.py b/src/ml_tooling/data/base_data.py
index ce93934..551e91d 100644
--- a/src/ml_tooling/data/base_data.py
+++ b/src/ml_tooling/data/base_data.py
@@ -113,6 +113,10 @@ class Dataset(metaclass=abc.ABCMeta):
 
         return x, y
 
+    @property
+    def features(self):
+        return self.x.columns.tolist()
+
     def _load_prediction_data(self, *args, **kwargs) -> pd.DataFrame:
         pred_data = self.load_prediction_data(*args, **kwargs)
         if pred_data.empty:

ENH: Datasets should have a way of listing available features
**Is your feature request related to a problem? Please describe.**
When doing EDA, it would be useful to have a way to describe what features are available

**Describe the solution you'd like**
Having a `.features` attribute that shows what features are available on the dataset

**Describe alternatives you've considered**
What other functionality apart from listing the feature names would be relevant to display? 
Can we use this with feature selection to create feature masks?

diff --git a/tests/test_datasets/test_dataset.py b/tests/test_datasets/test_dataset.py
index 0e8b0bd..f15e3d3 100644
--- a/tests/test_datasets/test_dataset.py
+++ b/tests/test_datasets/test_dataset.py
@@ -10,6 +10,15 @@ class TestDataset:
         result = str(iris_dataset())
         assert result == "<IrisData - Dataset>"
 
+    def test_feature_names_access_works_correctly(self, iris_dataset):
+        dataset = iris_dataset()
+        assert dataset.features == [
+            "sepal length (cm)",
+            "sepal width (cm)",
+            "petal length (cm)",
+            "petal width (cm)",
+        ]
+
     def test_dataset_x_attribute_access_works_correctly(self, iris_dataset):
         dataset = iris_dataset()
         assert dataset._x is None

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov
3.7
requirements.txt dev-requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
appdirs==1.4.4
attrs==20.2.0
Babel==2.14.0
certifi==2020.6.20
cfgv==3.1.0
chardet==3.0.4
coverage==5.2.1
cycler==0.10.0
distlib==0.3.9
docutils==0.19
dohq-artifactory==0.7.382
filelock==3.12.2
identify==1.4.25
idna==2.10
imagesize==1.4.1
importlib-metadata==6.7.0
iniconfig==1.0.0
Jinja2==3.1.6
joblib==0.17.0
kiwisolver==1.2.0
MarkupSafe==2.1.5
matplotlib==3.3.2
-e git+https://github.com/andersbogsnes/ml_tooling.git@7c7dc586efb28b681f86ce09fc0da8e3cab68b82#egg=ml_tooling
nodeenv==1.4.0
numpy==1.19.2
packaging==24.0
pandas==1.1.3
Pillow==7.2.0
platformdirs==4.0.0
pluggy==0.13.1
pre-commit==2.7.1
py==1.9.0
pyaml==20.4.0
Pygments==2.17.2
PyJWT==1.7.1
pyparsing==2.4.7
pytest==6.1.1
pytest-cov==2.10.1
python-dateutil==2.8.1
pytz==2020.1
PyYAML==5.3.1
requests==2.24.0
scikit-learn==0.23.1
scikit-optimize==0.8.1
scipy==1.5.2
six==1.15.0
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinx-rtd-theme==2.0.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
SQLAlchemy==1.3.19
threadpoolctl==2.1.0
toml==0.10.1
tomli==2.0.1
tox==3.28.0
typing_extensions==4.7.1
urllib3==1.25.10
virtualenv==20.26.6
zipp==3.15.0

name: ml_tooling
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - appdirs==1.4.4
      - attrs==20.2.0
      - babel==2.14.0
      - certifi==2020.6.20
      - cfgv==3.1.0
      - chardet==3.0.4
      - coverage==5.2.1
      - cycler==0.10.0
      - distlib==0.3.9
      - docutils==0.19
      - dohq-artifactory==0.7.382
      - filelock==3.12.2
      - identify==1.4.25
      - idna==2.10
      - imagesize==1.4.1
      - importlib-metadata==6.7.0
      - iniconfig==1.0.0
      - jinja2==3.1.6
      - joblib==0.17.0
      - kiwisolver==1.2.0
      - markupsafe==2.1.5
      - matplotlib==3.3.2
      - nodeenv==1.4.0
      - numpy==1.19.2
      - packaging==24.0
      - pandas==1.1.3
      - pillow==7.2.0
      - platformdirs==4.0.0
      - pluggy==0.13.1
      - pre-commit==2.7.1
      - py==1.9.0
      - pyaml==20.4.0
      - pygments==2.17.2
      - pyjwt==1.7.1
      - pyparsing==2.4.7
      - pytest==6.1.1
      - pytest-cov==2.10.1
      - python-dateutil==2.8.1
      - pytz==2020.1
      - pyyaml==5.3.1
      - requests==2.24.0
      - scikit-learn==0.23.1
      - scikit-optimize==0.8.1
      - scipy==1.5.2
      - six==1.15.0
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinx-rtd-theme==2.0.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - sqlalchemy==1.3.19
      - threadpoolctl==2.1.0
      - toml==0.10.1
      - tomli==2.0.1
      - tox==3.28.0
      - typing-extensions==4.7.1
      - urllib3==1.25.10
      - virtualenv==20.26.6
      - zipp==3.15.0
prefix: /opt/conda/envs/ml_tooling

tests/test_datasets/test_dataset.py::TestDataset::test_feature_names_access_works_correctly
tests/test_datasets/test_dataset.py::TestDataset::test_repr_is_correct tests/test_datasets/test_dataset.py::TestDataset::test_dataset_x_attribute_access_works_correctly tests/test_datasets/test_dataset.py::TestDataset::test_dataset_y_attribute_access_works_correctly tests/test_datasets/test_dataset.py::TestDataset::test_cant_modify_x_and_y tests/test_datasets/test_dataset.py::TestDataset::test_dataset_has_validation_set_errors_correctly tests/test_datasets/test_dataset.py::TestDataset::test_dataset_that_returns_empty_training_data_errors_correctly tests/test_datasets/test_dataset.py::TestDataset::test_dataset_raises_when_load_prediction_data_returns_empty tests/test_datasets/test_dataset.py::TestDataset::test_cannot_instantiate_an_abstract_baseclass tests/test_datasets/test_dataset.py::TestDataset::test_can_copy_one_dataset_into_another
src/ml_tooling/data/base_data.py CHANGELOG.md
src/ml_tooling/data/base_data.py CHANGELOG.md