RFC switch to Polars as the default dataframe lib in our examples

We now support polars as an output for our transformers and `ColumnTransformer`, but our examples use `pd.DataFrame`.

Our `datasets` module also returnes either a numpy array or a pandas DataFrame.

I'm suggesting that we enable datasets to return a polars dataframe, and to switch our examples from pandas to polars.

This has a few benefits:
- Polars on users' systems takes advantage of multi-core CPUs which is the case for pretty much all users these days. So it's quite faster in most cases.
- Pandas is dealing with issues related to Arrow, and even if they don't require Arrow as a required dependency, there will be behavior changes whether Arrow is installed or not at least on String Dtype.

Another thing is the (in)stability issues related to Pandas API where we need to deal with deprecation warnings very often. Although I'm not sure how stable the API is on the places where we touch the API on the polars side (maybe cc @MarcoGorelli )

WDYT @scikit-learn/core-devs @scikit-learn/documentation-team @scikit-learn/contributor-experience-team 

This is not really a core part of our library, but what we put in our examples and our default choices affect people since many learn from our examples.

COMMENT:
Ok, it seems that we have the "2. Making scikit-learn dataframe native" discussion in this issue anyway. I few personal thoughts:
**I would love to have a dataframe native ML framework.** I just don't know if its worth to turn scikit-learn into this or to make a new API design for it.

General considerations:
- Which dataframe library should we choose to adapt? This has the potential of becoming an endless and fruitless discussion (polars, pandas, pass arrow using duckdb, ...). The more general, the more tradeoffs.
- Which problem does it solve? Different people might have different problems in mind.

Polars specific:
- Lazy frames are a key feature of polars. I don't see how that would work out in scikit-learn pipelines where the full data is passed from each step to the next.
- Polars expressions are already a great API for data preparation pipelines. What's missing is the learning part (stateful transforms), i.e. `my_lazy_df.with_columns(pl.col("A") - pl.col("A").mean())` only misses to save the mean of A in order to be applied later at prediction time (call of `predict` or `transform`) where the expression `pl.col("A").mean()` should get replaced by this saved value.

History [1]:
- Keep in mind that the original design of scikit-learn was meant for matrix/2d-array data `X`, mostly with implied C-contiguity, and there are quite some use cases, too:
  - data from sensors
  - pairwise distances
  - etc (experts could fill many more point)
- Then came the `ColumnTransformer` ([v0.20](https://scikit-learn.org/stable/whats_new/v0.20.html#id25)) as an entry gate for heterogeneous tabular data, aka dataframes. But after the column transformer, all data is considered of the same data type. This made things like passing the information which column is categorical quite hard, see #18894 (I'm still not 100% convinced of the solution: circumvent the pipeline with the ordinal encoder in the first place!)
- With [SLEP018](https://scikit-learn-enhancement-proposals.readthedocs.io/en/latest/slep018/proposal.html) implemented in [v1.2](https://scikit-learn.org/stable/whats_new/v1.2.html#id8), estimators can output dataframes, but internally, (large) numpy arrays are processed, just the return value is wrapped in a dataframe (to my understanding).
- Even in our current design and working with a 2d-array from the beginning, we still make a lot of data copies during the processing of a pipeline, potentially in each and every pipeline step.

[1] This is my understanding, I became a part of scikit-learn much later, and I'm not a historian.

Labels: RFC