BUG: Decision trees: Incorrect/missing handling of missing values in `tree.decision_path(X)`

### Describe the bug

NaNs handling is missing from the function `tree.decision_path`, hence NaNs may end up in the incorrect path (i.e. `tree.decision_path` returns incorrect ouput).

See PR https://github.com/scikit-learn/scikit-learn/pull/32280 with the fix.

### Steps/Code to Reproduce

```Python
import numpy as np
from sklearn.tree import DecisionTreeClassifier, plot_tree

X = [0, np.nan, np.nan, 2, 3]
y = [0, 0,      0,      1, 1]
X = np.array(X).reshape(-1, 1)
tree = DecisionTreeClassifier().fit(X, y)
print(tree.apply(X))
print(tree.decision_path(X).toarray())
```

### Expected Results

Prints:
```
[1 1 1 2 2]

[[1 1 0]
 [1 1 0]
 [1 1 0]
 [1 0 1]
 [1 0 1]]
```

The NaNs are in the same leaf than the 0, so they have the same decision path.

### Actual Results

Prints:
```
[1 1 1 2 2]

[[1 1 0]
 [1 0 1]
 [1 0 1]
 [1 0 1]
 [1 0 1]]
```

The NaNs or in the same leaf than the 0, but have a different decision path.

### Versions

```shell
System:
    python: 3.12.11 (main, Aug 18 2025, 19:19:11) [Clang 20.1.4 ]
executable: /home/arthur/dev-perso/scikit-learn/sklearn-env/bin/python
   machine: Linux-6.14.0-32-generic-x86_64-with-glibc2.39

Python dependencies:
      sklearn: 1.8.dev0
          pip: None
   setuptools: 80.9.0
        numpy: 2.3.3
        scipy: 1.16.2
       Cython: 3.1.4
       pandas: 2.3.2
   matplotlib: 3.10.6
       joblib: 1.5.2
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: /home/arthur/dev-perso/scikit-learn/sklearn-env/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-8fb3d286.so
        version: 0.3.30
threading_layer: pthreads
   architecture: Haswell

       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: /home/arthur/dev-perso/scikit-learn/sklearn-env/lib/python3.12/site-packages/scipy.libs/libscipy_openblas-b75cc656.so
        version: 0.3.29.dev
threading_layer: pthreads
   architecture: Haswell

       user_api: openmp
   internal_api: openmp
    num_threads: 16
         prefix: libgomp
       filepath: /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0
        version: None
```

COMMENT:
Thank you @cakedev0 for this clear bug report and for providing the linked PR #32280 with the fix!

This is indeed an important issue that affects the correctness of decision path outputs when dealing with missing values. The discrepancy you've highlighted between `tree.apply(X)` (which correctly handles NaNs by sending them to the same leaf as the corresponding non-NaN values) and `tree.decision_path(X)` (which fails to properly trace the path for NaN values) could lead to incorrect interpretations in model explainability workflows.

## Technical Analysis

From your example, it's clear that:
1. **Expected behavior**: NaN values and the value `0` should follow the same decision path since they end up in the same leaf (node 1)
2. **Actual behavior**: The decision paths differ, with NaNs incorrectly showing they went through different splits

This bug could particularly impact:
- **Model interpretability tools** that rely on `decision_path()` to explain predictions
- **Feature importance calculations** that trace decision paths  
- **Debugging workflows** where users need to understand how missing values are handled

## Potential Solution Considerations

I noticed that PR #32280 addresses this. Some questions that might be worth considering for the implementation:

1. **Consistency**: Does the fix ensure that the missing value handling in `decision_path()` exactly mirrors the logic used during training and in `apply()`?
2. **Performance**: Are there any performance implications, especially for datasets with many missing values?
3. **Edge cases**: How does the fix handle scenarios with multiple features containing NaNs?

## Testing Suggestions

Beyond the provided example, it might be valuable to test:
- Multi-feature datasets with missing values in different combinations
- Regression trees (in addition to classification)
- Different missing value patterns (all NaN, mixed NaN/values, etc.)

Thank you again for catching this inconsistency and providing a solution. This kind of attention to detail helps maintain the reliability of scikit-learn's tree implementations!

Best regards,
Comet Assistant

Labels: Bug, Needs Triage