Repository: sktime/sktime
Pull request #7066 (2024-09-01 06:23:35)

[ENH] `GroupbyCategoryForecaster` for applying panel forecasting by category or segment
#### Reference Issues/PRs
Closes  #7050

#### What does this implement/fix? Explain your changes.
Implements a composite that allows users to fit-predict different forecasters for each group, where the groups are assigned according to a series-to-primitive transformation.


#### Does your contribution introduce a new dependency? If yes, which one?
No

#### What should a reviewer concentrate their feedback on?

1. Is this name ok?
2. Is the implemented test enough?

#### Did you add any tests for the change?

Yes, would be happy to hear feedback on the test too.


#### PR checklist


##### For all contributions
- [x] I've added myself to the [list of contributors](https://github.com/sktime/sktime/blob/main/CONTRIBUTORS.md) with any new badges I've earned :-)
- [x] Optionally, for added estimators: I've added myself and possibly to the `maintainers` tag - do this if you want to become the owner or maintainer of an estimator you added.
  See here for further details on the [algorithm maintainer role](https://www.sktime.net/en/latest/get_involved/governance.html#algorithm-maintainers).
- [x] The PR title starts with either [ENH], [MNT], [DOC], or [BUG]. [BUG] - bugfix, [MNT] - CI, test framework, [ENH] - adding or improving code, [DOC] - writing or improving documentation or docstrings.

##### For new estimators
- [x] I've added the estimator to the API reference - in `docs/source/api_reference/taskname.rst`, follow the pattern.
- [x] I've added one or more illustrative usage examples to the docstring, in a pydocstyle compliant `Examples` section.
- [x] If the estimator relies on a soft dependency, I've set the `python_dependencies` tag and ensured
  dependency isolation, see the [estimator dependencies guide](https://www.sktime.net/en/latest/developer_guide/dependencies.html#adding-a-soft-dependency).

<!--
Thanks for contributing!
-->



Patch:
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 8abb45cbb..9a425a816 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -6,7 +6,7 @@ Contributors
 <!-- Please add your badges to .all-contibutorsrc -->
 
 <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
-[![All Contributors](https://img.shields.io/badge/all_contributors-296-orange.svg)](#contributors)
+[![All Contributors](https://img.shields.io/badge/all_contributors-298-orange.svg)](#contributors)
 <!-- ALL-CONTRIBUTORS-BADGE:END -->
 
 This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
@@ -276,24 +276,26 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ronnie-llamado"><img src="https://avatars.githubusercontent.com/ronnie-llamado?s=100" width="100px;" alt="Ronnie Llamado"/><br /><sub><b>Ronnie Llamado</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ronnie-llamado" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/rnkuhns"><img src="https://avatars0.githubusercontent.com/u/26907244?v=4?s=100" width="100px;" alt="Ryan Kuhns"/><br /><sub><b>Ryan Kuhns</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=RNKuhns" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=RNKuhns" title="Documentation">📖</a> <a href="#tutorial-RNKuhns" title="Tutorials">✅</a> <a href="#example-RNKuhns" title="Examples">💡</a> <a href="#ideas-RNKuhns" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3ARNKuhns" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=RNKuhns" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/achieveordie"><img src="https://avatars.githubusercontent.com/u/54197164?v=4?s=100" width="100px;" alt="Sagar Mishra"/><br /><sub><b>Sagar Mishra</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Aachieveordie" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=achieveordie" title="Code">💻</a> <a href="#ideas-achieveordie" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-achieveordie" title="Project Management">📆</a> <a href="https://github.com/sktime/sktime/commits?author=achieveordie" title="Tests">⚠️</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/SaiRevanth25"><img src="https://avatars.githubusercontent.com/SaiRevanth25?s=100" width="100px;" alt="Sai Revanth Gowravajhala"/><br /><sub><b>Sai Revanth Gowravajhala</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SaiRevanth25" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3ASaiRevanth25" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://sajay.online"><img src="https://avatars2.githubusercontent.com/u/25329624?v=4?s=100" width="100px;" alt="Sajaysurya Ganesh"/><br /><sub><b>Sajaysurya Ganesh</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Documentation">📖</a> <a href="#design-sajaysurya" title="Design">🎨</a> <a href="#example-sajaysurya" title="Examples">💡</a> <a href="#ideas-sajaysurya" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Tests">⚠️</a> <a href="#tutorial-sajaysurya" title="Tutorials">✅</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/SamiAlavi"><img src="https://avatars.githubusercontent.com/u/32700289?v=4?s=100" width="100px;" alt="Sami Alavi"/><br /><sub><b>Sami Alavi</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SamiAlavi" title="Code">💻</a> <a href="#maintenance-SamiAlavi" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/SamruddhiNavale"><img src="https://avatars.githubusercontent.com/u/86359115?v=4?s=100" width="100px;" alt="Samruddhi Navale"/><br /><sub><b>Samruddhi Navale</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SamruddhiNavale" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sanjayk0508"><img src="https://avatars.githubusercontent.com/u/102804548?v=4?s=100" width="100px;" alt="Sanjay Kumar"/><br /><sub><b>Sanjay Kumar</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sanjayk0508" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/deysanjeeb"><img src="https://avatars.githubusercontent.com/u/39940629?v=4?s=100" width="100px;" alt="Sanjeeb Dey"/><br /><sub><b>Sanjeeb Dey</b></sub></a><br /><a href="#maintenance-deysanjeeb" title="Maintenance">🚧</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/deysanjeeb"><img src="https://avatars.githubusercontent.com/u/39940629?v=4?s=100" width="100px;" alt="Sanjeeb Dey"/><br /><sub><b>Sanjeeb Dey</b></sub></a><br /><a href="#maintenance-deysanjeeb" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sssilvar"><img src="https://avatars.githubusercontent.com/u/16252054?v=4?s=100" width="100px;" alt="Santiago Smith Silva"/><br /><sub><b>Santiago Smith Silva</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sssilvar" title="Code">💻</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/Saptarshi-Bandopadhyay"><img src="https://avatars.githubusercontent.com/u/88289395?v=4?s=100" width="100px;" alt="Saptarshi Bandopadhyay"/><br /><sub><b>Saptarshi Bandopadhyay</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Saptarshi-Bandopadhyay" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Saransh-cpp"><img src="https://avatars.githubusercontent.com/u/74055102?v=4?s=100" width="100px;" alt="Saransh Chopra"/><br /><sub><b>Saransh Chopra</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Saransh-cpp" title="Documentation">📖</a> <a href="#infra-Saransh-cpp" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/satya-pattnaik-77a430144/"><img src="https://avatars.githubusercontent.com/u/22102468?v=4?s=100" width="100px;" alt="Satya Prakash Pattnaik"/><br /><sub><b>Satya Prakash Pattnaik</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=satya-pattnaik" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/dasgupsa"><img src="https://avatars2.githubusercontent.com/u/10398956?v=4?s=100" width="100px;" alt="Saurabh Dasgupta"/><br /><sub><b>Saurabh Dasgupta</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=dasgupsa" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/SebasKoel"><img src="https://avatars3.githubusercontent.com/u/66252156?v=4?s=100" width="100px;" alt="Sebastiaan Koel"/><br /><sub><b>Sebastiaan Koel</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SebasKoel" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=SebasKoel" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/shagn"><img src="https://avatars.githubusercontent.com/u/16029092?v=4?s=100" width="100px;" alt="Sebastian Hagn"/><br /><sub><b>Sebastian Hagn</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=shagn" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/bastisar"><img src="https://avatars.githubusercontent.com/u/142449680?v=4?s=100" width="100px;" alt="Sebastian Hien"/><br /><sub><b>Sebastian Hien</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=bastisar" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Abastisar" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=bastisar" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/ShivamPathak99"><img src="https://avatars.githubusercontent.com/u/98941325?s=400&v=4?s=100" width="100px;" alt="Shivam Pathak"/><br /><sub><b>Shivam Pathak</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ShivamPathak99" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/AurumnPegasus"><img src="https://avatars.githubusercontent.com/u/54315149?v=4?s=100" width="100px;" alt="Shivansh Subramanian"/><br /><sub><b>Shivansh Subramanian</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/ShivamPathak99"><img src="https://avatars.githubusercontent.com/u/98941325?s=400&v=4?s=100" width="100px;" alt="Shivam Pathak"/><br /><sub><b>Shivam Pathak</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ShivamPathak99" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/AurumnPegasus"><img src="https://avatars.githubusercontent.com/u/54315149?v=4?s=100" width="100px;" alt="Shivansh Subramanian"/><br /><sub><b>Shivansh Subramanian</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><img src="https://gravatar.com/avatar/cbdbaac712ae282d730cd3028e862d45?s=400&d=robohash&r=x?s=100" width="100px;" alt="Shlok Sabarwal"/><br /><sub><b>Shlok Sabarwal</b></sub><br /><a href="https://github.com/sktime/sktime/commits?author=ssabarwal" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ShreeshaM07"><img src="https://avatars.githubusercontent.com/u/120820143?s=400&v=4?s=100" width="100px;" alt="Shreesha M"/><br /><sub><b>Shreesha M</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3AShreeshaM07" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=ShreeshaM07" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=ShreeshaM07" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sbuse"><img src="https://avatars.githubusercontent.com/u/24408707?v=4?s=100" width="100px;" alt="Simon B."/><br /><sub><b>Simon B.</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sbuse" title="Code">💻</a></td>
@@ -301,10 +303,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/solomon-botchway-a1383821b/"><img src="https://avatars.githubusercontent.com/u/62394255?v=4?s=100" width="100px;" alt="Solomon Botchway"/><br /><sub><b>Solomon Botchway</b></sub></a><br /><a href="#maintenance-snnbotchway" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/khrapovs"><img src="https://avatars.githubusercontent.com/u/3774663?v=4?s=100" width="100px;" alt="Stanislav Khrapov"/><br /><sub><b>Stanislav Khrapov</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=khrapovs" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/steenrotsman"><img src="https://avatars.githubusercontent.com/u/78110080?s=400&v=4?s=100" width="100px;" alt="Stijn J. Rotman"/><br /><sub><b>Stijn J. Rotman</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=steenrotsman" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=steenrotsman" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/SveaMeyer13"><img src="https://avatars.githubusercontent.com/u/46671894?v=4?s=100" width="100px;" alt="Svea Marie Meyer"/><br /><sub><b>Svea Marie Meyer</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SveaMeyer13" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=SveaMeyer13" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/TNTran92"><img src="https://avatars.githubusercontent.com/u/55965636?v=4?s=100" width="100px;" alt="TNTran92"/><br /><sub><b>TNTran92</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=TNTran92" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/SveaMeyer13"><img src="https://avatars.githubusercontent.com/u/46671894?v=4?s=100" width="100px;" alt="Svea Marie Meyer"/><br /><sub><b>Svea Marie Meyer</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SveaMeyer13" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=SveaMeyer13" title="Code">💻</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/TNTran92"><img src="https://avatars.githubusercontent.com/u/55965636?v=4?s=100" width="100px;" alt="TNTran92"/><br /><sub><b>TNTran92</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=TNTran92" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Taise228"><img src="https://avatars.githubusercontent.com/u/95762401?s=400&v=4?s=100" width="100px;" alt="Taisei Yamamoto"/><br /><sub><b>Taisei Yamamoto</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Taise228" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://thayeylolu.github.io/portfolio/"><img src="https://avatars.githubusercontent.com/u/13348874?v=4?s=100" width="100px;" alt="Taiwo Owoseni"/><br /><sub><b>Taiwo Owoseni</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=thayeylolu" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/lnthach"><img src="https://avatars0.githubusercontent.com/u/7788363?v=4?s=100" width="100px;" alt="Thach Le Nguyen"/><br /><sub><b>Thach Le Nguyen</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=lnthach" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=lnthach" title="Tests">⚠️</a></td>
@@ -312,10 +314,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/tombh"><img src="https://avatars.githubusercontent.com/u/160835?s=80&v=4?s=100" width="100px;" alt="Thomas Buckley-Houston"/><br /><sub><b>Thomas Buckley-Houston</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Atombh" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xxl4tomxu98"><img src="https://avatars.githubusercontent.com/u/62292177?s=40&v=4?s=100" width="100px;" alt="Tom Xu"/><br /><sub><b>Tom Xu</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xxl4tomxu98" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=xxl4tomxu98" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/tpvasconcelos"><img src="https://avatars.githubusercontent.com/u/17701527?v=4?s=100" width="100px;" alt="Tomas P. de Vasconcelos"/><br /><sub><b>Tomas P. de Vasconcelos</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Atpvasconcelos" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=tpvasconcelos" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/tch"><img src="https://avatars3.githubusercontent.com/u/184076?v=4?s=100" width="100px;" alt="Tomasz Chodakowski"/><br /><sub><b>Tomasz Chodakowski</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=tch" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=tch" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Atch" title="Bug reports">🐛</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="http://www.timeseriesclassification.com"><img src="https://avatars1.githubusercontent.com/u/9594042?v=4?s=100" width="100px;" alt="Tony Bagnall"/><br /><sub><b>Tony Bagnall</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=TonyBagnall" title="Code">💻</a> <a href="#business-TonyBagnall" title="Business development">💼</a> <a href="https://github.com/sktime/sktime/commits?author=TonyBagnall" title="Documentation">📖</a> <a href="#design-TonyBagnall" title="Design">🎨</a> <a href="#eventOrganizing-TonyBagnall" title="Event Organizing">📋</a> <a href="#fundingFinding-TonyBagnall" title="Funding Finding">🔍</a> <a href="#ideas-TonyBagnall" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-TonyBagnall" title="Project Management">📆</a> <a href="#question-TonyBagnall" title="Answering Questions">💬</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3ATonyBagnall" title="Reviewed Pull Requests">👀</a> <a href="#talk-TonyBagnall" title="Talks">📢</a> <a href="#data-TonyBagnall" title="Data">🔣</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/tch"><img src="https://avatars3.githubusercontent.com/u/184076?v=4?s=100" width="100px;" alt="Tomasz Chodakowski"/><br /><sub><b>Tomasz Chodakowski</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=tch" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=tch" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Atch" title="Bug reports">🐛</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="http://www.timeseriesclassification.com"><img src="https://avatars1.githubusercontent.com/u/9594042?v=4?s=100" width="100px;" alt="Tony Bagnall"/><br /><sub><b>Tony Bagnall</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=TonyBagnall" title="Code">💻</a> <a href="#business-TonyBagnall" title="Business development">💼</a> <a href="https://github.com/sktime/sktime/commits?author=TonyBagnall" title="Documentation">📖</a> <a href="#design-TonyBagnall" title="Design">🎨</a> <a href="#eventOrganizing-TonyBagnall" title="Event Organizing">📋</a> <a href="#fundingFinding-TonyBagnall" title="Funding Finding">🔍</a> <a href="#ideas-TonyBagnall" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-TonyBagnall" title="Project Management">📆</a> <a href="#question-TonyBagnall" title="Answering Questions">💬</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3ATonyBagnall" title="Reviewed Pull Requests">👀</a> <a href="#talk-TonyBagnall" title="Talks">📢</a> <a href="#data-TonyBagnall" title="Data">🔣</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/onyekaugochukwu"><img src="https://avatars.githubusercontent.com/u/92909501?v=4?s=100" width="100px;" alt="Ugochukwu Onyeka"/><br /><sub><b>Ugochukwu Onyeka</b></sub></a><br /><a href="#business-onyekaugochukwu" title="Business development">💼</a> <a href="https://github.com/sktime/sktime/commits?author=onyekaugochukwu" title="Documentation">📖</a> <a href="#ideas-onyekaugochukwu" title="Ideas, Planning, & Feedback">🤔</a> <a href="#mentoring-onyekaugochukwu" title="Mentoring">🧑‍🏫</a> <a href="#projectManagement-onyekaugochukwu" title="Project Management">📆</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/utsavcoding"><img src="https://avatars3.githubusercontent.com/u/55446385?v=4?s=100" width="100px;" alt="Utsav Kumar Tiwari"/><br /><sub><b>Utsav Kumar Tiwari</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=utsavcoding" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=utsavcoding" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vandit98"><img src="https://avatars.githubusercontent.com/u/91458535?v=4?s=100" width="100px;" alt="Vandit Tyagi"/><br /><sub><b>Vandit Tyagi</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vandit98" title="Documentation">📖</a></td>
@@ -323,10 +325,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/victordremov"><img src="https://avatars.githubusercontent.com/u/32140716?s=100" width="100px;" alt="Viktor Dremov"/><br /><sub><b>Viktor Dremov</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=victordremov" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ViktorKaz"><img src="https://avatars0.githubusercontent.com/u/33499138?v=4?s=100" width="100px;" alt="ViktorKaz"/><br /><sub><b>ViktorKaz</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ViktorKaz" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=ViktorKaz" title="Documentation">📖</a> <a href="#design-ViktorKaz" title="Design">🎨</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vnicholson1"><img src="?s=100" width="100px;" alt="Vincent Nicholson"/><br /><sub><b>Vincent Nicholson</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vnicholson1" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/VyomkeshVyas"><img src="?s=100" width="100px;" alt="Vyomkesh Vyas"/><br /><sub><b>Vyomkesh Vyas</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Documentation">📖</a> <a href="#example-VyomkeshVyas" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/wayneadams"><img src="https://avatars.githubusercontent.com/u/15034841?s=400&u=d717e9945910bcc844c5e64cd56d570c6cc4e8e6&v=4?s=100" width="100px;" alt="Wayne Adams"/><br /><sub><b>Wayne Adams</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=wayneadams" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/VyomkeshVyas"><img src="?s=100" width="100px;" alt="Vyomkesh Vyas"/><br /><sub><b>Vyomkesh Vyas</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Documentation">📖</a> <a href="#example-VyomkeshVyas" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Tests">⚠️</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/wayneadams"><img src="https://avatars.githubusercontent.com/u/15034841?s=400&u=d717e9945910bcc844c5e64cd56d570c6cc4e8e6&v=4?s=100" width="100px;" alt="Wayne Adams"/><br /><sub><b>Wayne Adams</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=wayneadams" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/fr1ll"><img src="https://avatars.githubusercontent.com/u/29168593?v=4?s=100" width="100px;" alt="Will Sanger"/><br /><sub><b>Will Sanger</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=fr1ll" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=fr1ll" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/templierw/"><img src="https://github.com/templierw.png?s=100" width="100px;" alt="William Templier"/><br /><sub><b>William Templier</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=templierw" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/magittan"><img src="https://avatars0.githubusercontent.com/u/14024202?v=4?s=100" width="100px;" alt="William Zheng"/><br /><sub><b>William Zheng</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=magittan" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=magittan" title="Tests">⚠️</a></td>
@@ -334,10 +336,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/wpdonders"><img src="https://avatars.githubusercontent.com/u/1868824?v=4?s=100?s=100" width="100px;" alt="Wouter Donders"/><br /><sub><b>Wouter Donders</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=wpdonders" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=wpdonders" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/XinyuWuu"><img src="https://avatars.githubusercontent.com/u/57612792?v=4?s=100" width="100px;" alt="Xinyu Wu"/><br /><sub><b>Xinyu Wu</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3AXinyuWuu" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=XinyuWuu" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=XinyuWuu" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/yairbeer"><img src="https://avatars.githubusercontent.com/yairbeer?s=100" width="100px;" alt="Yair Beer"/><br /><sub><b>Yair Beer</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=yairbeer" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/yann-hallouard/"><img src="https://avatars.githubusercontent.com/YHallouard?s=100" width="100px;" alt="Yann Hallouard"/><br /><sub><b>Yann Hallouard</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=YHallouard" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=YHallouard" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/MEMEO-PRO"><img src="https://avatars.githubusercontent.com/memeo-pro?s=100" width="100px;" alt="Yash Edake"/><br /><sub><b>Yash Edake</b></sub></a><br /><a href="#maintenance-memeo-pro" title="Maintenance">🚧</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Amemeo-pro" title="Bug reports">🐛</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/yann-hallouard/"><img src="https://avatars.githubusercontent.com/YHallouard?s=100" width="100px;" alt="Yann Hallouard"/><br /><sub><b>Yann Hallouard</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=YHallouard" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=YHallouard" title="Tests">⚠️</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/MEMEO-PRO"><img src="https://avatars.githubusercontent.com/memeo-pro?s=100" width="100px;" alt="Yash Edake"/><br /><sub><b>Yash Edake</b></sub></a><br /><a href="#maintenance-memeo-pro" title="Maintenance">🚧</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Amemeo-pro" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/YashKhare20"><img src="https://avatars.githubusercontent.com/u/92680366?s=400?s=100" width="100px;" alt="Yash Khare"/><br /><sub><b>Yash Khare</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=YashKhare20" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=YashKhare20" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/yashlamba"><img src="https://avatars.githubusercontent.com/u/44164398?v=4?s=100" width="100px;" alt="Yash Lamba"/><br /><sub><b>Yash Lamba</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=yashlamba" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xuyxu"><img src="https://avatars2.githubusercontent.com/u/22359569?v=4?s=100" width="100px;" alt="Yi-Xuan Xu"/><br /><sub><b>Yi-Xuan Xu</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xuyxu" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=xuyxu" title="Tests">⚠️</a> <a href="#maintenance-xuyxu" title="Maintenance">🚧</a> <a href="https://github.com/sktime/sktime/commits?author=xuyxu" title="Documentation">📖</a></td>
@@ -345,10 +347,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ZiyaoWei"><img src="https://avatars.githubusercontent.com/u/940823?v=4?s=100" width="100px;" alt="Ziyao Wei"/><br /><sub><b>Ziyao Wei</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ZiyaoWei" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/aa25desh"><img src="https://avatars1.githubusercontent.com/u/29518290?v=4?s=100" width="100px;" alt="aa25desh"/><br /><sub><b>aa25desh</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=aa25desh" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Aaa25desh" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/abandus"><img src="https://avatars2.githubusercontent.com/u/46486474?v=4?s=100" width="100px;" alt="abandus"/><br /><sub><b>abandus</b></sub></a><br /><a href="#ideas-abandus" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=abandus" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/adoherty21"><img src="https://avatars.githubusercontent.com/u/52799751?s=400&v=4?s=100" width="100px;" alt="adoherty21"/><br /><sub><b>adoherty21</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Aadoherty21" title="Bug reports">🐛</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/bethrice44"><img src="https://avatars.githubusercontent.com/u/11226988?v=4?s=100" width="100px;" alt="bethrice44"/><br /><sub><b>bethrice44</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Abethrice44" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=bethrice44" title="Code">💻</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Abethrice44" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=bethrice44" title="Tests">⚠️</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/adoherty21"><img src="https://avatars.githubusercontent.com/u/52799751?s=400&v=4?s=100" width="100px;" alt="adoherty21"/><br /><sub><b>adoherty21</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Aadoherty21" title="Bug reports">🐛</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/bethrice44"><img src="https://avatars.githubusercontent.com/u/11226988?v=4?s=100" width="100px;" alt="bethrice44"/><br /><sub><b>bethrice44</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Abethrice44" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=bethrice44" title="Code">💻</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Abethrice44" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=bethrice44" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/big-o"><img src="https://avatars1.githubusercontent.com/u/1134151?v=4?s=100" width="100px;" alt="big-o"/><br /><sub><b>big-o</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=big-o" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=big-o" title="Tests">⚠️</a> <a href="#design-big-o" title="Design">🎨</a> <a href="#ideas-big-o" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Abig-o" title="Reviewed Pull Requests">👀</a> <a href="#tutorial-big-o" title="Tutorials">✅</a> <a href="#mentoring-big-o" title="Mentoring">🧑‍🏫</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/bobbys-dev"><img src="https://avatars.githubusercontent.com/bobbys-dev?s=100" width="100px;" alt="bobbys"/><br /><sub><b>bobbys</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=bobbys-dev" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/brettkoonce"><img src="https://avatars2.githubusercontent.com/u/11281814?v=4?s=100" width="100px;" alt="brett koonce"/><br /><sub><b>brett koonce</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=brettkoonce" title="Documentation">📖</a></td>
@@ -356,10 +358,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/chizzi25"><img src="https://avatars3.githubusercontent.com/u/67911243?v=4?s=100" width="100px;" alt="chizzi25"/><br /><sub><b>chizzi25</b></sub></a><br /><a href="#blog-chizzi25" title="Blogposts">📝</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/chrisholder"><img src="https://avatars.githubusercontent.com/u/4674372?v=4?s=100" width="100px;" alt="chrisholder"/><br /><sub><b>chrisholder</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=chrisholder" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=chrisholder" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/commits?author=chrisholder" title="Documentation">📖</a> <a href="#design-chrisholder" title="Design">🎨</a> <a href="#example-chrisholder" title="Examples">💡</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/morestart"><img src="https://avatars.githubusercontent.com/u/35556811?s=100" width="100px;" alt="ctl"/><br /><sub><b>ctl</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Amorestart" title="Bug reports">🐛</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/danbartl"><img src="https://avatars.githubusercontent.com/u/19947407?v=4?s=100" width="100px;" alt="danbartl"/><br /><sub><b>danbartl</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Adanbartl" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=danbartl" title="Code">💻</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Adanbartl" title="Reviewed Pull Requests">👀</a> <a href="#talk-danbartl" title="Talks">📢</a> <a href="https://github.com/sktime/sktime/commits?author=danbartl" title="Tests">⚠️</a> <a href="#tutorial-danbartl" title="Tutorials">✅</a> <a href="#video-danbartl" title="Videos">📹</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/hamzahiqb"><img src="https://avatars3.githubusercontent.com/u/10302415?v=4?s=100" width="100px;" alt="hamzahiqb"/><br /><sub><b>hamzahiqb</b></sub></a><br /><a href="#infra-hamzahiqb" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/danbartl"><img src="https://avatars.githubusercontent.com/u/19947407?v=4?s=100" width="100px;" alt="danbartl"/><br /><sub><b>danbartl</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Adanbartl" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=danbartl" title="Code">💻</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Adanbartl" title="Reviewed Pull Requests">👀</a> <a href="#talk-danbartl" title="Talks">📢</a> <a href="https://github.com/sktime/sktime/commits?author=danbartl" title="Tests">⚠️</a> <a href="#tutorial-danbartl" title="Tutorials">✅</a> <a href="#video-danbartl" title="Videos">📹</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/hamzahiqb"><img src="https://avatars3.githubusercontent.com/u/10302415?v=4?s=100" width="100px;" alt="hamzahiqb"/><br /><sub><b>hamzahiqb</b></sub></a><br /><a href="#infra-hamzahiqb" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/hiqbal2"><img src="https://avatars3.githubusercontent.com/u/10302415?v=4?s=100" width="100px;" alt="hiqbal2"/><br /><sub><b>hiqbal2</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=hiqbal2" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jesellier"><img src="https://avatars0.githubusercontent.com/u/51952076?v=4?s=100" width="100px;" alt="jesellier"/><br /><sub><b>jesellier</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jesellier" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jschemm"><img src="https://avatars.githubusercontent.com/u/81151346?v=4?s=100" width="100px;" alt="jschemm"/><br /><sub><b>jschemm</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jschemm" title="Code">💻</a></td>
@@ -367,10 +369,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/matteogales"><img src="https://avatars0.githubusercontent.com/u/9269326?v=4?s=100" width="100px;" alt="matteogales"/><br /><sub><b>matteogales</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=matteogales" title="Code">💻</a> <a href="#design-matteogales" title="Design">🎨</a> <a href="#ideas-matteogales" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/oleskiewicz"><img src="https://avatars1.githubusercontent.com/u/5682158?v=4?s=100" width="100px;" alt="oleskiewicz"/><br /><sub><b>oleskiewicz</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=oleskiewicz" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=oleskiewicz" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=oleskiewicz" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/pabworks"><img src="https://avatars.githubusercontent.com/u/32725127?v=4?s=100" width="100px;" alt="pabworks"/><br /><sub><b>pabworks</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=pabworks" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=pabworks" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/xloem"><img src="?s=100" width="100px;" alt="patiently pending world peace"/><br /><sub><b>patiently pending world peace</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xloem" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/raishubham1"><img src="https://avatars3.githubusercontent.com/u/29356417?v=4?s=100" width="100px;" alt="raishubham1"/><br /><sub><b>raishubham1</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=raishubham1" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/xloem"><img src="?s=100" width="100px;" alt="patiently pending world peace"/><br /><sub><b>patiently pending world peace</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xloem" title="Code">💻</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/raishubham1"><img src="https://avatars3.githubusercontent.com/u/29356417?v=4?s=100" width="100px;" alt="raishubham1"/><br /><sub><b>raishubham1</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=raishubham1" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/simone-pignotti"><img src="https://avatars1.githubusercontent.com/u/44410066?v=4?s=100" width="100px;" alt="simone-pignotti"/><br /><sub><b>simone-pignotti</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=simone-pignotti" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Asimone-pignotti" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sophijka"><img src="https://avatars2.githubusercontent.com/u/47450591?v=4?s=100" width="100px;" alt="sophijka"/><br /><sub><b>sophijka</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sophijka" title="Documentation">📖</a> <a href="#maintenance-sophijka" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sri1419"><img src="https://avatars2.githubusercontent.com/u/65078278?v=4?s=100" width="100px;" alt="sri1419"/><br /><sub><b>sri1419</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sri1419" title="Code">💻</a></td>
@@ -378,6 +380,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vedazeren"><img src="https://avatars3.githubusercontent.com/u/63582874?v=4?s=100" width="100px;" alt="vedazeren"/><br /><sub><b>vedazeren</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vedazeren" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=vedazeren" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vincent-nich12"><img src="https://avatars3.githubusercontent.com/u/36476633?v=4?s=100" width="100px;" alt="vincent-nich12"/><br /><sub><b>vincent-nich12</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vincent-nich12" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vollmersj"><img src="https://avatars2.githubusercontent.com/u/12613127?v=4?s=100" width="100px;" alt="vollmersj"/><br /><sub><b>vollmersj</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vollmersj" title="Documentation">📖</a></td>
+    </tr>
+    <tr>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xiaobenbenecho"><img src="https://avatars.githubusercontent.com/u/17461849?v=4?s=100" width="100px;" alt="xiaobenbenecho"/><br /><sub><b>xiaobenbenecho</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xiaobenbenecho" title="Code">💻</a></td>
     </tr>
   </tbody>
diff --git a/docs/source/api_reference/forecasting.rst b/docs/source/api_reference/forecasting.rst
index 02930a77f..d90d06a2a 100644
--- a/docs/source/api_reference/forecasting.rst
+++ b/docs/source/api_reference/forecasting.rst
@@ -53,6 +53,7 @@ Pipelines can also be constructed using ``*``, ``**``, ``+``, and ``|`` dunders.
     MultiplexForecaster
     ForecastX
     ForecastByLevel
+    GroupbyCategoryForecaster
     Permute
     HierarchyEnsembleForecaster
     TransformSelectForecaster
diff --git a/docs/source/api_reference/transformations.rst b/docs/source/api_reference/transformations.rst
index 69b7a5c42..9915445bf 100644
--- a/docs/source/api_reference/transformations.rst
+++ b/docs/source/api_reference/transformations.rst
@@ -99,6 +99,17 @@ Pipeline building - AutoML, switches and multiplexing
     TransformIf
     Id
 
+Pipeline building - Logging
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. currentmodule:: sktime.transformations.compose
+
+.. autosummary::
+    :toctree: auto_generated/
+    :template: class.rst
+
+    Logger
+
 Sklearn and pandas adapters
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/extension_templates/classification.py b/extension_templates/classification.py
index 5e8671782..82f51cf90 100644
--- a/extension_templates/classification.py
+++ b/extension_templates/classification.py
@@ -100,8 +100,9 @@ class MyTimeSeriesClassifier(BaseClassifier):
         # --------------
         "X_inner_mtype": "numpy3D",  # which type do _fit/_predict accept, usually
         "y_inner_mtype": "numpy1D",  # which type do _fit/_predict return, usually
-        # this is either "numpy3D", "pd-multiindex" or "nested_univ" (nested df). Other
-        # types are allowable, see datatypes/panel/_registry.py for options.
+        # this is one of "numpy3D" (instance, variable, time point),
+        # "pd-multiindex" (row index: instance, time; column index: variable) or other
+        # machine types, see datatypes/panel/_registry.py for options.
         "capability:multivariate": False,  # ability to handle multivariate X
         "capability:multioutput": False,  # ability to predict multiple columns in y
         "capability:unequal_length": False,
diff --git a/extension_templates/clustering.py b/extension_templates/clustering.py
index 5ce4633c9..d6c4e2784 100644
--- a/extension_templates/clustering.py
+++ b/extension_templates/clustering.py
@@ -97,8 +97,9 @@ class MyClusterer(BaseClusterer):
         # estimator tags
         # --------------
         "X_inner_mtype": "numpy3D",  # which type do _fit/_predict accept, usually
-        # this is either "numpy3D" or "nested_univ" (nested pd.DataFrame). Other
-        # types are allowable, see datatypes/panel/_registry.py for options.
+        # this is one of "numpy3D" (instance, variable, time point),
+        # "pd-multiindex" (row index: instance, time; column index: variable) or other
+        # machine types, see datatypes/panel/_registry.py for options.
         "capability:multivariate": False,
         "capability:unequal_length": False,
         "capability:missing_values": False,
diff --git a/sktime/forecasting/compose/__init__.py b/sktime/forecasting/compose/__init__.py
index 5e4423c55..22319429d 100644
--- a/sktime/forecasting/compose/__init__.py
+++ b/sktime/forecasting/compose/__init__.py
@@ -12,6 +12,7 @@ __all__ = [
     "TransformedTargetForecaster",
     "ForecastingPipeline",
     "ForecastX",
+    "GroupbyCategoryForecaster",
     "DirectTabularRegressionForecaster",
     "DirectTimeSeriesRegressionForecaster",
     "MultioutputTabularRegressionForecaster",
@@ -41,7 +42,10 @@ from sktime.forecasting.compose._ensemble import (
 )
 from sktime.forecasting.compose._fallback import FallbackForecaster
 from sktime.forecasting.compose._fhplex import FhPlexForecaster
-from sktime.forecasting.compose._grouped import ForecastByLevel
+from sktime.forecasting.compose._grouped import (
+    ForecastByLevel,
+    GroupbyCategoryForecaster,
+)
 from sktime.forecasting.compose._hierarchy_ensemble import HierarchyEnsembleForecaster
 from sktime.forecasting.compose._ignore_x import IgnoreX
 from sktime.forecasting.compose._multiplexer import MultiplexForecaster
diff --git a/sktime/forecasting/compose/_grouped.py b/sktime/forecasting/compose/_grouped.py
index 75b873f36..f7b367939 100644
--- a/sktime/forecasting/compose/_grouped.py
+++ b/sktime/forecasting/compose/_grouped.py
@@ -1,11 +1,22 @@
 # copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
 """Implements compositors for performing forecasting by group."""
 
+from typing import Union
+
+import pandas as pd
+
+from sktime.base._meta import _HeterogenousMetaEstimator
 from sktime.datatypes import ALL_TIME_SERIES_MTYPES, mtype_to_scitype
+from sktime.forecasting.base import BaseForecaster
 from sktime.forecasting.base._delegate import _DelegatedForecaster
+from sktime.forecasting.croston import Croston
+from sktime.forecasting.naive import NaiveForecaster
+from sktime.forecasting.trend import PolynomialTrendForecaster
+from sktime.transformations.base import BaseTransformer
+from sktime.transformations.series.adi_cv import ADICVTransformer
 
-__author__ = ["fkiraly"]
-__all__ = ["ForecastByLevel"]
+__author__ = ["fkiraly", "felipeangelimvieira"]
+__all__ = ["ForecastByLevel", "GroupbyCategoryForecaster"]
 
 
 class ForecastByLevel(_DelegatedForecaster):
@@ -122,3 +133,601 @@ class ForecastByLevel(_DelegatedForecaster):
         params = [{"forecaster": f, "groupby": g} for g in groupbys]
 
         return params
+
+
+class GroupbyCategoryForecaster(BaseForecaster, _HeterogenousMetaEstimator):
+    """Compositor that utilizes varying forecasters based on inferred category.
+
+    Applies a series-to-primitives transformer on a given time series. Series are
+    grouped by the generated value from the transformer, and the corresponding
+    forecaster is used to predict the time series.
+
+    Differently from `TransformSelectForecaster`, this compositor passes all timeseries
+    of a given category to the forecaster, instead of passing only one at a time.
+
+    Parameters
+    ----------
+    forecasters : dict[sktime forecasters]
+        dict of forecasters with the key corresponding to categories generated
+        by the given transformer and the value corresponding to a sktime forecaster.
+
+    transformer : sktime transformer, default = ADICVTransformer()
+        A series-to-primitives sk-time transformer that generates a value
+        which can be used to quantify a choice of forecaster for the time series.
+
+        Note: To ensure correct functionality, the transformer must store the
+        generated category in the first column of the returned values when
+        the transform() or fit_transform() functions are called.
+
+    fallback_forecaster : sktime forecaster | None, Optional
+        A fallback forecaster that will be used if the category generated by
+        the transformer does not match any of the given forecasters.
+
+    Raises
+    ------
+    AssertionError: If a valid transformer (an instance of BaseTransformer)
+    is not passed or if valid forecasters (instances of BaseForecaster) are not given.
+
+    Examples
+    --------
+    This example showcases how the GroupbyCategoryForecaster can be utilized to select
+    appropriate forecasters on the basis of the time series category determined by
+    the ADICVTransformer!
+
+    >>> from sktime.forecasting.compose import GroupbyCategoryForecaster
+    >>> from sktime.forecasting.croston import Croston
+    >>> from sktime.forecasting.trend import PolynomialTrendForecaster
+    >>> from sktime.forecasting.naive import NaiveForecaster
+    >>> from sktime.transformations.series.adi_cv import ADICVTransformer
+
+    # Importing the methods which can generate data of specific categories
+    depending on their variance and average demand intervals.
+
+    >>> from sktime.transformations.series.tests.test_adi_cv import (
+    ...     _generate_erratic_series)
+
+    # The forecaster is defined which accepts a dictionary of forecasters,
+    a transformer and optionally a fallback_forecaster
+
+    >>> group_forecaster = GroupbyCategoryForecaster(
+    ...     forecasters =
+    ...         {"smooth": NaiveForecaster(),
+    ...         "erratic": Croston(),
+    ...         "intermittent": PolynomialTrendForecaster()},
+    ...     transformer=ADICVTransformer(features=["class"]))
+
+    >>> generated_data = _generate_erratic_series()
+
+    # The fit function firstly passes the data through the given transformer
+    # to generate a given category. This category can be seen by the variable
+    # self.category_.
+
+    >>> group_forecaster = group_forecaster.fit(generated_data, fh=50)
+    >>> #print(f"The chosen category is: {group_forecaster.category}")
+
+    >>> # Print out the predicted value over the given forecasting horizon!
+    >>> # print(group_forecaster.predict(fh=50, X=None))
+    """
+
+    _tags = {
+        "y_inner_mtype": [
+            "pd.DataFrame",
+            "pd-multiindex",
+            "pd_multiindex_hier",
+        ],
+        "X_inner_mtype": [
+            "pd.DataFrame",
+            "pd-multiindex",
+            "pd_multiindex_hier",
+        ],
+        "scitype:y": "both",
+        "ignores-exogeneous-X": False,
+        "requires-fh-in-fit": False,
+        "enforce_index_type": None,
+        "authors": ["felipeangelimvieira", "shlok191"],
+        "maintainers": ["felipeangelimvieira"],
+        "python_version": None,
+    }
+
+    _steps_attr = "_forecasters"
+
+    def __init__(
+        self,
+        forecasters,
+        transformer=None,
+        fallback_forecaster=None,
+    ):
+        # saving arguments to object storage
+        if transformer is not None:
+            self.transformer = transformer
+
+        else:
+            self.transformer = ADICVTransformer(features=["class"])
+
+        self.forecasters = forecasters
+        self.fallback_forecaster = fallback_forecaster
+
+        self.transformer_ = self.transformer.clone()
+
+        super().__init__()
+
+        # validating passed arguments
+        assert isinstance(self.transformer_, BaseTransformer)
+
+        for forecaster in forecasters.values():
+            assert isinstance(forecaster, BaseForecaster)
+
+        # All checks OK!
+
+        # Assigning all capabilities on the basis of the capabilities
+        # of the passed forecasters
+        true_if_all_tags = {
+            "ignores-exogeneous-X": True,
+            "X-y-must-have-same-index": True,
+            "enforce_index_type": True,
+            "handles-missing-data": True,
+            "capability:insample": True,
+            "capability:pred_int": True,
+            "capability:pred_int:insample": True,
+        }
+
+        # Extrapolating values for flags that should be True if they are
+        # True for all of the given forecasters!
+        for tag in true_if_all_tags.keys():
+            # Checking the equivalent forecaster tags
+            true_for_all = True
+
+            for forecaster in self.forecasters.values():
+                # Fetching the forecaster tags
+                forecaster_tags = forecaster.get_tags()
+
+                if tag not in forecaster_tags or forecaster_tags[tag] is False:
+                    true_for_all = False
+                    break
+
+            # Perform this check for the fallback forecaster too
+            if fallback_forecaster is not None and (
+                tag not in fallback_forecaster.get_tags()
+                or fallback_forecaster.get_tags()[tag] is False
+            ):
+                true_for_all = False
+
+            true_if_all_tags[tag] = true_for_all
+
+        # Extrapolating values for flags that should be True if they are
+        # True for any of the given forecasters!
+        true_if_any_tags = {
+            "requires-fh-in-fit": True,
+            "X-y-must-have-same-index": True,
+        }
+
+        # Create a list of forecasters
+        forecasters = list(self.forecasters.items())
+
+        if self.fallback_forecaster is not None:
+            forecasters.append(("", self.fallback_forecaster))
+
+        # Update the tags by iterating through all tags
+        for tag in true_if_any_tags:
+            self._anytagis_then_set(tag, True, False, forecasters)
+
+        # Update the tags
+        self.set_tags(**true_if_all_tags)
+
+        # Finally, dynamically adding implementation of probabilistic
+        # functions depending on the tags set.
+        if self.get_tags()["capability:pred_int"]:
+            self._predict_interval = _predict_interval
+            self._predict_var = _predict_var
+            self._predict_proba = _predict_proba
+
+    def _fit(self, y, X=None, fh=None):
+        """Fit forecaster to training data.
+
+        private _fit containing the core logic, called from fit
+
+        For the _fit function to work as intended, the transformer
+        must generate and store the extrapolated category in the
+        first column.
+
+        Writes to self:
+            Sets fitted model attributes ending in "_".
+
+        Parameters
+        ----------
+        y : Pd.Series
+            The target time series to which we fit the data.
+
+        fh : ForecastingHorizon | None, optional (default=None)
+            The forecasting horizon with the steps ahead to predict.
+
+        X : Pd.Series | None, optional (default=None)
+            No exogenous variables are used for this.
+
+        Returns
+        -------
+        self : reference to self
+
+        Raises
+        ------
+        ValueError: If the extrapolated category has no provided forecaster
+        and if there is no fallback forecaster provided to the object!
+
+        Example:
+
+        If the passed transformer is an ADICVTransformer(), and the generated
+        series is a lumpy series; however, if there is no key matching "lumpy"
+        in the forecasters parameter, the fallback_forecaster will be used.
+        Additionally, if the fallback_forecaster is None, a ValueError will be thrown.
+        """
+        # passing time series through the provided transformer!
+
+        self.category_ = self.transformer_.fit_transform(X=y, y=X).iloc[:, 0]
+        self.forecasters_ = {}
+
+        if y.index.nlevels == 1:
+            # Handle case where y is a DataFrame without panel
+            self.grouped_by_category_ = [(self.category_.values[0], None)]
+        else:
+            self.grouped_by_category_ = self.category_.groupby(self.category_)
+
+        for category, group in self.grouped_by_category_:
+            # check if we have an available forecaster
+            if category not in self.forecasters:
+                if self.fallback_forecaster is None:
+                    raise ValueError(
+                        "Forecaster not provided for given"
+                        + f"time series of type {self.category_}"
+                        + "and no fallback forecaster provided to use for this case."
+                    )
+
+                # Adopt the fallback forecaster if possible
+                else:
+                    chosen_forecaster_ = self.fallback_forecaster.clone()
+
+            else:
+                chosen_forecaster_ = self.forecasters[category].clone()
+
+            y_category = self._loc_group(y, group)
+
+            X_category = None
+            if X is not None:
+                X_category = self._loc_group(X, group)
+
+            # fitting the forecaster!
+            chosen_forecaster_.fit(y=y_category, X=X_category, fh=fh)
+
+            self.forecasters_[category] = chosen_forecaster_
+
+        return self
+
+    def _predict(self, fh, X):
+        """Forecast time series at future horizon.
+
+        private _predict containing the core logic, called from predict
+
+        State required:
+            Requires state to be "fitted".
+
+        Accesses in self:
+            Fitted model attributes ending in "_"
+            self.cutoff
+
+        Parameters
+        ----------
+        fh : guaranteed to be ForecastingHorizon or None, optional (default=None)
+            The forecasting horizon with the steps ahead to to predict.
+            If not passed in _fit, guaranteed to be passed here
+
+        X : sktime time series object, optional (default=None)
+            guaranteed to be of an mtype in self.get_tag("X_inner_mtype")
+            Exogeneous time series for the forecast
+
+        Returns
+        -------
+        y_pred : sktime time series object
+            should be of the same type as seen in _fit, as in "y_inner_mtype" tag
+            Point predictions
+        """
+        # Obtain the prediction values for the given horizon.
+
+        return self._iterate_predict_method_over_categories("predict", X=X, fh=fh)
+
+    def _update(self, y, X=None, update_params=True):
+        """Update time series to incremental training data.
+
+        Does not update the extrapolated category from the given
+        transformer, and thus the chosen forecaster remains the same.
+
+        State required:
+            Requires state to be "fitted".
+
+        Accesses in self:
+            Fitted model attributes ending in "_"
+            self.cutoff
+
+        Writes to self:
+            Sets fitted model attributes ending in "_", if update_params=True.
+            Does not write to self if update_params=False.
+
+        Parameters
+        ----------
+        y : sktime time series object
+            guaranteed to be of an mtype in self.get_tag("y_inner_mtype")
+            Time series with which to update the forecaster.
+            if self.get_tag("scitype:y")=="univariate":
+                guaranteed to have a single column/variable
+            if self.get_tag("scitype:y")=="multivariate":
+                guaranteed to have 2 or more columns
+            if self.get_tag("scitype:y")=="both": no restrictions apply
+        X :  sktime time series object, optional (default=None)
+            guaranteed to be of an mtype in self.get_tag("X_inner_mtype")
+            Exogeneous time series for the forecast
+        update_params : bool, optional (default=True)
+            whether model parameters should be updated
+
+        Returns
+        -------
+        self : reference to self
+        """
+        for category, group in self.grouped_by_category_:
+            y_category = self._loc_group(y, group)
+            X_category = self._loc_group(X, group)
+            self.forecasters_[category].update(
+                y=y_category, X=X_category, update_params=update_params
+            )
+        return self
+
+    @classmethod
+    def get_test_params(cls, parameter_set="default"):
+        """Return testing parameter settings for the estimator.
+
+        Parameters
+        ----------
+        parameter_set : str, default="default"
+            Name of the set of test parameters to return, for use in tests. If no
+            special parameters are defined for a value, will return `"default"` set.
+            There are currently no reserved values for forecasters.
+
+        Returns
+        -------
+        params : dict or list of dict, default = {}
+            Parameters to create testing instances of the class
+            Each dict are parameters to construct an "interesting" test instance, i.e.,
+            `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
+            `create_test_instance` uses the first (or only) dictionary in `params`
+        """
+        param1 = {
+            "forecasters": {
+                "smooth": NaiveForecaster(),
+                "erratic": PolynomialTrendForecaster(),
+                "intermittent": Croston(),
+                "lumpy": NaiveForecaster(),
+            },
+            "transformer": ADICVTransformer(features=["class"]),
+            "fallback_forecaster": None,
+        }
+
+        # Attempting to utilize the fallback forecaster
+        param2 = {
+            "forecasters": {},
+            "transformer": ADICVTransformer(features=["class"]),
+            "fallback_forecaster": Croston(),
+        }
+
+        params = [param1, param2]
+        return params
+
+    def _iterate_predict_method_over_categories(
+        self, methodname: str, X=None, **kwargs
+    ):
+        """
+        Iterate over the forecasters and call the given method on each one.
+
+        This method helps to avoid code duplication when implementing the
+        predict, predict_interval, predict_var, and predict_proba methods.
+
+        Parameters
+        ----------
+        methodname : str
+            The name of the method to call on each forecaster.
+        X : pd.DataFrame, optional (default=None)
+            The exogenous variables to use for the forecast.
+        **kwargs : dict
+            Additional keyword arguments to pass to the method.
+
+        Returns
+        -------
+        pd.DataFrame
+            The predicted values given methodname.
+        """
+        y_preds = []
+        for category, group in self.grouped_by_category_:
+            X_category = X
+            if X_category is not None:
+                X_category = self._loc_group(X, group)
+            else:
+                X_category = None
+
+            forecaster = self.forecasters_[category]
+            y_pred = getattr(forecaster, methodname)(X=X_category, **kwargs)
+            y_preds.append(y_pred)
+        y_preds = pd.concat(y_preds, axis=0).sort_index()
+        return y_preds
+
+    @property
+    def _forecasters(self):
+        """Provides an internal list of the forecasters available.
+
+        Each list item is a tuple of the format (category, forecaster)
+        where the category for which the respective forecaster is chosen
+        and the forecaster itself as the values for each tuple.
+
+        Returns
+        -------
+        forecasters : list[tuple[str, strsktime forecasters]]
+            The list of forecasters which is returned. Also includes the
+            fallback forecaster with the category: "fallback_forecaster"
+        """
+        return list(self.forecasters.items()) + [
+            "fallback_forecaster",
+            self.fallback_forecaster,
+        ]
+
+    @_forecasters.setter
+    def _forecasters(self, new_forecasters):
+        """Provide new values for the forecasters.
+
+        Parameters
+        ----------
+        new_forecasters : list[tuple[str, strsktime forecasters]]
+            The list of new forecasters to update the object's forecasters with
+        """
+        # Accepting in possible new forecasters
+        for category, forecaster in new_forecasters:
+            # We assign this in a different way
+            if category != "fallback_forecaster":
+                self.forecasters[category] = forecaster
+
+            else:
+                self.fallback_forecaster = forecaster
+
+    def _loc_group(self, df: pd.DataFrame, group: Union[pd.DataFrame, None]):
+        """
+        Return the indexes of the given dataframe that match the given group.
+
+        The case where the group is None is used to handle pd.DataFrame mtypes that
+        do not have a panel level.
+
+        Parameters
+        ----------
+        df : pd.DataFrame
+            The dataframe to locate the group in.
+        group : pd.DataFrame or None
+            The group to locate in the dataframe.
+
+        Returns
+        -------
+        pd.DataFrame
+            The indexes of the dataframe that match the given group.
+        """
+        if df is None or group is None:
+            return df
+        return df.loc[df.index.droplevel(-1).map(lambda x: x in group.index),]
+
+
+# Function implementations that will be added dynamically
+# if the conditions are met. explained further above!
+def _predict_interval(self, fh, X, coverage):
+    """Compute/return prediction quantiles for a forecast.
+
+    private _predict_interval containing the core logic,
+        called from predict_interval and possibly predict_quantiles
+
+    State required:
+        Requires state to be "fitted".
+
+    Accesses in self:
+        Fitted model attributes ending in "_"
+        self.cutoff
+
+    Parameters
+    ----------
+    fh : guaranteed to be ForecastingHorizon
+        The forecasting horizon with the steps ahead to to predict.
+    X :  sktime time series object, optional (default=None)
+        guaranteed to be of an mtype in self.get_tag("X_inner_mtype")
+        Exogeneous time series for the forecast
+    coverage : list of float (guaranteed not None and floats in [0,1] interval)
+        nominal coverage(s) of predictive interval(s)
+
+    Returns
+    -------
+    pred_int : pd.DataFrame
+        Column has multi-index: first level is variable name from y in fit,
+            second level coverage fractions for which intervals were computed.
+                in the same order as in input `coverage`.
+            Third level is string "lower" or "upper", for lower/upper interval end.
+        Row index is fh, with additional (upper) levels equal to instance levels,
+            from y seen in fit, if y_inner_mtype is Panel or Hierarchical.
+        Entries are forecasts of lower/upper interval end,
+            for var in col index, at nominal coverage in second col index,
+            lower/upper depending on third col index, for the row index.
+            Upper/lower interval end forecasts are equivalent to
+            quantile forecasts at alpha = 0.5 - c/2, 0.5 + c/2 for c in coverage.
+    """
+    return self._iterate_predict_method_over_categories(
+        "predict_interval", X=X, fh=fh, coverage=coverage
+    )
+
+
+def _predict_var(self, fh, X=None, cov=False):
+    """Forecast variance at future horizon.
+
+    private _predict_var containing the core logic, called from predict_var
+
+    Parameters
+    ----------
+    fh : guaranteed to be ForecastingHorizon or None, optional (default=None)
+        The forecasting horizon with the steps ahead to to predict.
+        If not passed in _fit, guaranteed to be passed here
+    X :  sktime time series object, optional (default=None)
+        guaranteed to be of an mtype in self.get_tag("X_inner_mtype")
+        Exogeneous time series for the forecast
+    cov : bool, optional (default=False)
+        if True, computes covariance matrix forecast.
+        if False, computes marginal variance forecasts.
+
+    Returns
+    -------
+    pred_var : pd.DataFrame, format dependent on `cov` variable
+        If cov=False:
+            Column names are exactly those of `y` passed in `fit`/`update`.
+                For nameless formats, column index will be a RangeIndex.
+            Row index is fh, with additional levels equal to instance levels,
+                from y seen in fit, if y_inner_mtype is Panel or Hierarchical.
+            Entries are variance forecasts, for var in col index.
+            A variance forecast for given variable and fh index is a predicted
+                variance for that variable and index, given observed data.
+        If cov=True:
+            Column index is a multiindex: 1st level is variable names (as above)
+                2nd level is fh.
+            Row index is fh, with additional levels equal to instance levels,
+                from y seen in fit, if y_inner_mtype is Panel or Hierarchical.
+            Entries are (co-)variance forecasts, for var in col index, and
+                covariance between time index in row and col.
+            Note: no covariance forecasts are returned between different variables.
+    """
+    return self._iterate_predict_method_over_categories(
+        "predict_var", X=X, fh=fh, cov=cov
+    )
+
+
+def _predict_proba(self, fh, X, marginal=True):
+    """Compute/return fully probabilistic forecasts.
+
+    private _predict_proba containing the core logic, called from predict_proba
+
+    Parameters
+    ----------
+    fh : int, list, np.array or ForecastingHorizon (not optional)
+        The forecasting horizon encoding the time stamps to forecast at.
+        if has not been passed in fit, must be passed, not optional
+    X : sktime time series object, optional (default=None)
+            Exogeneous time series for the forecast
+        Should be of same scitype (Series, Panel, or Hierarchical) as y in fit
+        if self.get_tag("X-y-must-have-same-index"),
+            X.index must contain fh.index and y.index both
+    marginal : bool, optional (default=True)
+        whether returned distribution is marginal by time index
+
+    Returns
+    -------
+    pred_dist : sktime BaseDistribution
+        predictive distribution
+        if marginal=True, will be marginal distribution by time point
+        if marginal=False and implemented by method, will be joint
+    """
+    return self._iterate_predict_method_over_categories(
+        "predict_proba", X=X, fh=fh, marginal=marginal
+    )
diff --git a/sktime/transformations/compose/__init__.py b/sktime/transformations/compose/__init__.py
index b6b724c1c..128c35596 100644
--- a/sktime/transformations/compose/__init__.py
+++ b/sktime/transformations/compose/__init__.py
@@ -12,6 +12,7 @@ from sktime.transformations.compose._grouped import TransformByLevel
 from sktime.transformations.compose._id import Id
 from sktime.transformations.compose._invert import InvertTransform
 from sktime.transformations.compose._ixtox import IxToX
+from sktime.transformations.compose._logger import DataLog, Logger
 from sktime.transformations.compose._multiplex import MultiplexTransformer
 from sktime.transformations.compose._optional import OptionalPassthrough
 from sktime.transformations.compose._pipeline import TransformerPipeline
@@ -22,11 +23,13 @@ __author__ = ["fkiraly", "mloning", "miraep8", "aiwalter", "SveaMeyer13"]
 __all__ = [
     "ColumnwiseTransformer",
     "ColumnEnsembleTransformer",
+    "DataLog",
     "FeatureUnion",
     "FitInTransform",
     "Id",
     "InvertTransform",
     "IxToX",
+    "Logger",
     "MultiplexTransformer",
     "OptionalPassthrough",
     "TransformerPipeline",
diff --git a/sktime/transformations/compose/_logger.py b/sktime/transformations/compose/_logger.py
new file mode 100644
index 000000000..c8b9a4652
--- /dev/null
+++ b/sktime/transformations/compose/_logger.py
@@ -0,0 +1,295 @@
+"""Logging transformer."""
+
+# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
+
+__author__ = ["fkiraly"]
+__all__ = ["Logger"]
+
+from sktime.transformations.base import BaseTransformer
+from sktime.transformations.compose._common import CORE_MTYPES
+
+
+class Logger(BaseTransformer):
+    """Logging transformer, writes data to logging, and otherwise leaves it unchanged.
+
+    In methods, logs ``X`` and ``y`` to ``logger``.
+    The ``logger`` can us as ``logger_backend`` a python ``logging`` instance,
+    primarily for printing, with ``data`` logged as ``extra``,
+    or a custom ``DataLog`` instance to retrieve full objects and not just printouts.
+
+    Parameters
+    ----------
+    logger : str optional, default="sktime"
+        logger name to use, passed to ``logger_backend`` to identify
+        the unique logger instance referenced by ``get_logger``.
+
+    logger_backend : str, one of "logging" (default), "datalog"
+        Backend to use for logging.
+
+        * "logging": uses the standard Python logging module,
+          logs to ``logging.getLogger(logger)``
+        * "datalog": uses a multiton logger class for easy retrieval of data,
+          logs to ``DataLog(logger)``, with ``DataLog`` from
+          the ``transformations.compose`` module.
+
+        In either case, a reference to the logger can be retrieved
+        by calling ``obj.get_logger``, where ``obj`` is an instance of ``Logger``.
+
+    log_methods : str or list of str, default=``"transform"``
+        if ``"all"``, will log ``fit``, ``transform``, ``inverse_transform``;
+        if str or list of str, all strings must be from among the above,
+        and will log exactly the methods that are passed as str;
+        can also be ``"off""`` to disable logging entirely.
+
+    level : logging level, optional, default=logging.INFO
+        logging level, one of
+        ``logging.INFO``, ``logging.DEBUG``, ``logging.WARNING``,
+        ``logging.ERROR``
+
+    log_fitted_params : bool, optional, default=False
+        if True, will also write ``X`` and ``y`` seen in ``fit``
+        to ``self`` as ``X_`` and ``y_``, these can be retrieved
+        by calling ``get_fitted_params``.
+        If False, ``get_fitted_params`` will return an empty dict.
+
+    Examples
+    --------
+    >>> from sktime.transformations.compose import DataLog, Logger
+    >>> from sktime.datasets import load_airline
+    >>> from sktime.forecasting.naive import NaiveForecaster
+    >>> from sktime.transformations.series.detrend import Detrender
+    >>>
+    >>> # create a logger
+    >>> logger = Logger(logger="foo", log_methods="all", logger_backend="datalog")
+    >>> # create a pipeline that logs after detrending and before forecasting
+    >>> pipe = Detrender() * logger * NaiveForecaster(sp=12)
+    >>> pipe.fit(load_airline(), fh=[1, 2, 3])
+    >>> # get the log
+    >>> log = DataLog("foo").get_log()
+    """
+
+    _tags = {
+        "authors": "fkiraly",
+        "capability:inverse_transform": True,  # can the transformer inverse transform?
+        "univariate-only": False,  # can the transformer handle multivariate X?
+        "X_inner_mtype": CORE_MTYPES,  # which mtypes do _fit/_predict support for X?
+        # this can be a Panel mtype even if transform-input is Series, vectorized
+        "y_inner_mtype": CORE_MTYPES,  # which mtypes do _fit/_predict support for y?
+        "fit_is_empty": False,  # is fit empty and can be skipped? Yes = True
+        "transform-returns-same-time-index": True,
+        # does transform return have the same time index as input X
+        "handles-missing-data": True,  # can estimator handle missing data?
+    }
+
+    def __init__(
+        self,
+        logger="sktime",
+        logger_backend="logging",
+        log_methods="all",
+        level=None,
+        log_fitted_params=False,
+    ):
+        self.logger = logger
+        self.logger_backend = logger_backend
+        self.log_methods = log_methods
+        self.level = level
+        self.log_fitted_params = log_fitted_params
+        super().__init__()
+
+        if self.log_methods == "all":
+            self._log_methods = ["fit", "transform", "inverse_transform"]
+        elif self.log_methods == "off":
+            self._log_methods = []
+        elif isinstance(self.log_methods, str):
+            self._log_methods = [self.log_methods]
+        else:
+            self._log_methods = self.log_methods
+
+        if self.level is None:
+            import logging
+
+            self._level = logging.INFO
+        else:
+            self._level = self.level
+
+    @property
+    def get_logger(self):
+        if self.logger_backend == "logging":
+            import logging
+
+            return logging.getLogger(self.logger)
+        elif self.logger_backend == "datalog":
+            return DataLog(self.logger)
+
+    def _write_log(self, key, obj):
+        """Write log to logger.
+
+        Parameters
+        ----------
+        key : str
+            key to identify the object
+        obj : any
+            object to log
+        """
+        if self.logger_backend == "logging":
+            self.get_logger.log(self._level, key, extra=obj)
+        elif self.logger_backend == "datalog":
+            self.get_logger.log(key, obj)
+
+    def _fit(self, X, y=None):
+        """Fit transformer to X and y.
+
+        private _fit containing the core logic, called from fit
+
+        Parameters
+        ----------
+        X : pd.DataFrame
+            if self.get_tag("univariate-only")==True:
+                guaranteed to have a single column
+            if self.get_tag("univariate-only")==False: no restrictions apply
+        y : None, present only for interface compatibility
+
+        Returns
+        -------
+        self: reference to self
+        """
+        if "fit" in self._log_methods:
+            self._write_log("fit", {"X": X, "y": y})
+        if self.log_fitted_params:
+            self.X_ = X
+            self.y_ = y
+        return self
+
+    def _transform(self, X, y=None):
+        """Transform X and return a transformed version.
+
+        private _transform containing the core logic, called from transform
+
+        Parameters
+        ----------
+        X : any sktime compatible data, Series, Panel, or Hierarchical
+        y : optional, default=None
+            ignored, argument present for interface conformance
+
+        Returns
+        -------
+        X, identical to input
+        """
+        if "transform" in self._log_methods:
+            self._write_log("transform", {"X": X, "y": y})
+        return X
+
+    def _inverse_transform(self, X, y=None):
+        """Inverse transform X and return an inverse transformed version.
+
+        private _inverse_transform containing core logic, called from inverse_transform
+
+        Parameters
+        ----------
+        X : any sktime compatible data, Series, Panel, or Hierarchical
+        y : optional, default=None
+            ignored, argument present for interface conformance
+
+        Returns
+        -------
+        X, identical to input
+        """
+        if "inverse_transform" in self._log_methods:
+            self._write_log("inverse_transform", {"X": X, "y": y})
+        return X
+
+    @classmethod
+    def get_test_params(cls, parameter_set="default"):
+        """Return testing parameter settings for the estimator.
+
+        Parameters
+        ----------
+        parameter_set : str, default="default"
+            Name of the set of test parameters to return, for use in tests. If no
+            special parameters are defined for a value, will return ``"default"`` set.
+
+        Returns
+        -------
+        params : dict or list of dict
+        """
+        import logging
+
+        params0 = {}
+        params1 = {"logger": "bar", "log_methods": "off"}
+        params2 = {
+            "log_methods": ["transform", "inverse_transform"],
+            "log_fitted_params": True,
+            "level": logging.ERROR,
+        }
+        params3 = {"logger": "foo", "level": logging.DEBUG, "log_methods": "all"}
+        params4 = {"logger": "foo", "logger_backend": "datalog", "log_methods": "all"}
+        return [params0, params1, params2, params3, params4]
+
+
+def _multiton(cls):
+    """Turn a class into a multiton."""
+    instances = {}
+
+    def get_instance(key, *args, **kwargs):
+        if key not in instances:
+            instances[key] = cls(key, *args, **kwargs)
+        return instances[key]
+
+    return get_instance
+
+
+@_multiton
+class DataLog:
+    """Data logger.
+
+    Identified uniquely by a key, logs data in a list.
+    List contains tuples of (log_key : str, data : any).
+
+    Methods as below:
+
+    * ``log`` appends a tuple to the list.
+    * ``get_log`` returns the list.
+    * ``reset`` empties the list.
+
+    Parameters
+    ----------
+    key : str
+        key to identify the logger
+    """
+
+    def __init__(self, key):
+        self.key = key
+        self._log = []
+
+    def log(self, log_key, data):
+        """Log data.
+
+        Appends the following tuple to the log list: ``(log_key, data)``.
+
+        The full log can be read by calling ``get_log``.
+
+        Parameters
+        ----------
+        log_key : str
+            key to identify the data
+        data : any
+            data to log
+        """
+        self._log.append((log_key, data))
+        return self
+
+    def reset(self):
+        """Reset the log to the empty list."""
+        self._log = []
+        return self
+
+    def get_log(self):
+        """Read the log.
+
+        Returns
+        -------
+        log : list of tuple
+            Reference to the list containing the logged data,
+            list of tuples of (log_key : str, data : any)
+        """
+        return self._log


Test patch:
diff --git a/sktime/forecasting/compose/tests/test_groupbycategoryforecaster.py b/sktime/forecasting/compose/tests/test_groupbycategoryforecaster.py
new file mode 100644
index 000000000..0444e0809
--- /dev/null
+++ b/sktime/forecasting/compose/tests/test_groupbycategoryforecaster.py
@@ -0,0 +1,118 @@
+import itertools
+
+import numpy as np
+import pandas as pd
+import pytest
+
+from sktime.forecasting.compose import GroupbyCategoryForecaster
+from sktime.forecasting.naive import NaiveForecaster
+from sktime.transformations.base import BaseTransformer
+
+
+class PredefinedCategory(BaseTransformer):
+    _tags = {
+        "scitype:transform-input": "Panel",
+        "scitype:transform-output": "Panel",
+    }
+
+    def __init__(self, transform_output):
+        self.transform_output = transform_output
+        super().__init__()
+
+    def fit(self, X, y=None):
+        return self
+
+    def transform(self, X, y=None):
+        return self.transform_output
+
+
+@pytest.fixture
+def timeseries_index():
+    series_ids = [
+        ("A", "A1"),
+        ("A", "A2"),
+        ("B", "B1"),
+        ("B", "B2"),
+        ("C", "C1"),
+        ("C", "C2"),
+    ]
+    dates = pd.date_range(start="2020-01-01", periods=10, freq="D")
+
+    multiindex_tuples = [(*a, b) for a, b in itertools.product(series_ids, dates)]
+
+    return pd.MultiIndex.from_tuples(
+        multiindex_tuples, names=["level0", "level1", "dates"]
+    )
+
+
+@pytest.fixture
+def categories(timeseries_index):
+    unique_series = timeseries_index.droplevel(-1).unique()
+
+    categories = pd.DataFrame(
+        index=unique_series,
+        data={"category": np.arange(len(unique_series)) % 2},
+    )
+    categories.loc[("C", "C1"), "category"] = 3
+    return categories
+
+
+@pytest.fixture
+def timeseries(timeseries_index):
+    return pd.DataFrame(
+        index=timeseries_index,
+        data={"target": np.arange(len(timeseries_index))},
+    )
+
+
+def test_predefined_output(timeseries):
+    transform_output = pd.Series(["A"])
+    transformer = PredefinedCategory(transform_output=transform_output)
+
+    # Should completly ignore the input and return the predefined output
+    output = transformer.fit_transform(X=timeseries)
+
+    assert output.equals(transform_output)
+
+
+def test_predefined_output_groupby(timeseries, categories):
+    """Test if the correct forecasters are fitted for each category"""
+    categorizer = PredefinedCategory(transform_output=categories)
+    forecaster = GroupbyCategoryForecaster(
+        forecasters={
+            0: NaiveForecaster(strategy="mean"),
+            1: NaiveForecaster(strategy="drift"),
+        },
+        transformer=categorizer,
+        fallback_forecaster=NaiveForecaster(strategy="last"),
+    )
+
+    forecaster.fit(timeseries)
+    fitted_params = forecaster.get_fitted_params()
+    forecasters = fitted_params["forecasters"]
+    assert len(forecasters) == 3
+    assert forecasters[0].strategy == "mean"
+    assert forecasters[1].strategy == "drift"
+    assert forecasters[3].strategy == "last"
+
+
+def test_series_without_panel_level():
+    from sktime.datasets import load_airline
+    from sktime.transformations.series.adi_cv import ADICVTransformer
+
+    y = load_airline()
+    X = pd.DataFrame(0, index=pd.date_range("2020-01-01", periods=10), columns=["B"])
+
+    forecaster = GroupbyCategoryForecaster(
+        forecasters={
+            0: NaiveForecaster(strategy="mean"),
+            1: NaiveForecaster(strategy="drift"),
+        },
+        transformer=ADICVTransformer(features=["class"]),
+        fallback_forecaster=NaiveForecaster(strategy="last"),
+    )
+
+    forecaster.fit(y, X)
+    y_pred = forecaster.predict(X=X, fh=[1, 2, 3])
+
+    assert y_pred.index.nlevels == 1