Reverse Transform and a intelligent skip non existent columns for transformer and pipelines

### Describe the workflow you want to enable

I have almost implemented a wizard that will preprocess the data a user puts in. Than the training of Tensorflow networks will be done and also a integration REST API flow comes out. But here is the catch:

We implemented a auto feature preprocessing transformer and wanted to do so with a pipeline. This works very well as long as the input data has not changed or I do not want to apply a reverse transformation. But in my integration flow afterwards this is exactly the case. I have my features but not my targets, so the feature pipeline will not work (except with my workaround: faking the target data and after the transformer pipeline was applied remove the target columns). 

Okay that was Problemo 1. Here is Problemo numero due:

Since in regression use cases the scaled output from the network is not interesting to me, also not the one hot encoded feature vector in classification use cases. So I simply thought just use the pipeline and reverse transform it. But no there is no reverse transform method for pipelines. So heres my next workaround: We scan the pipeline and manually call the reverse transform method on each transformer recursevly. Okay now you are feeling my nausea. To make things even more complicated here also kicks in the columns problem since my predicted data only contains a subset of the previous data columns.

Would be lovely when this feature would be implemented.

```python

def _reverse_pipeline(dataset, transformer):
    """
        Iteratively calls the inverse operation of a transformer if available (else branch).
        If the transformer itself contains transformers, we recursively call them with this method.
        #Iterarecurception.
        
    """
    # DEV-Note: Before you read this let me say a few words:
    # 1stly: let me say sorry.
    # 2ndly: let me say I had no other choice.
    # Since Scikit learn nested trasnformer object pipelines 
    # does not support reverse transformation calls we had to
    # get creative. The result is this method. We will succecesivly
    # call any sub transformer apply reverse transform on it. 
    # But since it can be that some columns are not present
    # should replace those values by some dummy values. But
    # to replace it we would need the an example for each column.
    # Since this is getting now to much workarounds here I decided
    # we skip that and live with the fact that reverse transformation will
    # not work if for example you give in only a sub set of the one hot encoded
    # columns. But it will work if you only give the target value in, the scaler
    # should transform it back and also the one hot encoding should be reversed. 

    if isinstance(transformer, compose.ColumnTransformer):
        for sub_transformer in transformer.transformers_:
            dataset = _reverse_pipeline(dataset, sub_transformer)
    elif isinstance(transformer, tuple): 
        _, transformer, columns = transformer
        if isinstance(transformer, feature_selection.VarianceThreshold):
            return dataset
        if isinstance(transformer, custom_encoders.CorrelationThreshold):
            return dataset

        if len(columns) > 0 and hasattr(transformer, "inverse_transform"):
            features_in = transformer.feature_names_in_
            features_out = transformer.get_feature_names_out()
            features_gone = [c for c in dataset.columns if c not in features_out]

       
            subset = pd.DataFrame(columns=features_out)
            features_out = [c for c in features_out if c in dataset.columns]
            subset[features_out] = dataset[features_out]

            dataset.drop(features_out, axis=1, inplace=True)

            if subset.shape[0] > 0:
                dataset[features_in] = transformer.inverse_transform(subset)
            # dataset.drop(features_gone, axis=1, inplace=True)

    return dataset

```




```python
def select_pipeline(dataset, transformer_id, columns=None, **kwargs):
    if columns == None: 
        columns = dataset.columns

        transf_info = Transformers.get(transformer_id)
        pipeline_data = Transformers.load(transformer_id)
        feature_pipeline = pipeline_data["feature_pipeline"]
        label_pipeline = pipeline_data["label_pipeline"]

        if "type" not in transf_info or transf_info["type"] != "pipeline":
            raise Exception("Given id: " + str(transformer_id) + " does not match a valid pipeline.")

        dataset = dataset[columns]

        missing_cols = list(filter((lambda x: x not in dataset.columns), pipeline_data["columns_in"]))
        example_data = pipeline_data["example_data"]

        # fill missing columns with example data so that the transformer can 
        # transform the data even when the whole dataset is not present,
        # plz Scikit Learn implement autoignore of columns that are not given...
        for col in missing_cols:
            dataset[col] = example_data[col]
        


        for transformer in feature_pipeline:
            dataset = transformer.transform(dataset)
            dataset = pd.DataFrame(dataset, columns=transformer.get_feature_names_out())

        for transformer in label_pipeline:
            dataset = transformer.transform(dataset)
            dataset = pd.DataFrame(dataset, columns=transformer.get_feature_names_out())
      
        if missing_cols != None:
            # DEVNOTE: 
            # Since we might have faked our missing columns 
            # We have to remove either the missing columns itself,
            # or in case they have been encoded the newly created columns 
            # that where created out of our missing columns.
            cols_to_remove = []
            for m_col in missing_cols:
                
                if m_col in list(dataset.columns): # in case our column was not encoded the shame should be the same as before...
                    cols_to_remove.append(m_col)
                else: 
                    for col in list(dataset.columns): # quick and dirty: check if missing_column name with an underscore appears in newly created columns (encoding case, will not work if columns with the exact name and underscore appear accidentaly inside the base dataset)
                        if (col in m_col): cols_to_remove.append(col)


            dataset = dataset.drop(cols_to_remove, axis=1)

        return [dataset]
```

### Describe your proposed solution

Look in text above.

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
I am not sure about the request here since the inner code depends also on some pandas code which we cannot integrate into scikit-learn.

It would be better to reopen an issue with a well-defined feature request: provide some input data and a scikit-learn pipeline where the current API is limited and show the expected code one would expect to work.

Labels: New Feature, Needs Triage