RFC Deprecate FeatureUnion and make_union

Unless I'm missing something, to me `FeatureUnion` is just a `ColumnTransformer` where all transformers are applied to all features. So it's just a special case of `ColumnTransformer`.

```py
import pandas as pd
from sklearn.pipeline import FeatureUnion
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler

df = pd.DataFrame({"a": [1, 2, 3, 4], "b": [1, 2, 3, 4]})

fu = FeatureUnion([("std_1", StandardScaler()), ("std_2", StandardScaler())])
fu.set_output(transform="pandas")
print(fu.fit_transform(df))
   std_1__a  std_1__b  std_2__a  std_2__b
0 -1.341641 -1.341641 -1.341641 -1.341641
1 -0.447214 -0.447214 -0.447214 -0.447214
2  0.447214  0.447214  0.447214  0.447214
3  1.341641  1.341641  1.341641  1.341641

all_cols = slice(None)
ct = ColumnTransformer([("std_1", StandardScaler(), all_cols), ("std_2", StandardScaler(), all_cols)])
ct.set_output(transform="pandas")
print(ct.fit_transform(df))
   std_1__a  std_1__b  std_2__a  std_2__b
0 -1.341641 -1.341641 -1.341641 -1.341641
1 -0.447214 -0.447214 -0.447214 -0.447214
2  0.447214  0.447214  0.447214  0.447214
3  1.341641  1.341641  1.341641  1.341641
```

In addition, the parameters of `FeatureUnion` is a subset of the parameters of `ColumnTransformer`, so I don't see anything that one would be able to do with `FeatureUnion` but not with `ColumnTransformer`.

From a maintenance view, it duplicates the burden because they share almost no code and it's common that they suffer from the same bugs and  fixes have to be repeated in both classes. And usually one or the other keeps the bug for a while because we only implement a fix for one and forget about the other. In general the forgotten one is `FeatureUnion` btw :) (e.g. the latest one https://github.com/scikit-learn/scikit-learn/issues/32104 for `FeatureUnion` that was detected and fixed a while ago for `ColumnTransformer` https://github.com/scikit-learn/scikit-learn/issues/28260)

Finally, `FeatureUnion` has unresolved long standing issues like not cloning the transformers before fitting and modifying init parameters during fit, meaning that it does not follow our Transformer API.

Considering all that, I propose to deprecate `FeatureUnion`.

ping @scikit-learn/core-devs, did I miss something obvious ? what's your opinion about that ?

COMMENT:
I understand the argument of separation of concerns. The fact that scikit-learn doesn't have a `SelectColumns` or `SelectCols` makes it harder without using another lib. Maybe we should include a column selector transformer in scikit-learn ?
However, using the FeatureUnion + SelectColumns is a lot more verbose than using a ColumnTransformer
```py
FeatureUnion([
    (
        "std",
        Pipeline([
            ("select", ColumnSelector(["a", "b"])),
            ("std", StandardScaler()),
        ]),
    ),
    (
        "ohe",
        Pipeline([
            ("select", ColumnSelector(["c", "d"])),
            ("ohe", OneHotEncoder()),
        ]),
    ),
])
```
Compared to
```py
ColumnTransformer([
    ("std", StandardScaler(), ["a", "b"]),
    ("ohe", OneHotEncoder(), ["c", "d"]),
])
```
It's also less efficient because the whole dataset is passed to both transformers while in the column transformer, only the corresponding subset of columns is passed to each transformer. (it can have a big impact on memory usage if run in parallel)

That being said, I understand that removing it may disturb users habits, so instead we could maybe wrap it around a ColumnTransformer internally ? It would change the behavior though, e.g. internal cloning.

Labels: API, RFC, module:compose, module:pipeline