Repository: unionai-oss/pandera

Issue:
Pandas indexes are not coerced when `coerce=True` specified at schema level
**Describe the bug**
Pandas indexes are not coerced when `coerce=True` is specified at the schema level.

This subsequently causes a `SchemaError` to be raised later on, of the general form
```
pandera.errors.SchemaError: expected series '<name-of-series>' to have type x, got y
```

I believe the problem is here https://github.com/unionai-oss/pandera/blob/main/pandera/backends/pandas/container.py#L452. If `coerce=True` at the schema level, then the index should also be coerced. However, the code at present sets the `_coerce` attribute of the index schema instead of the `coerce` attribute. As a result, the `coerce` attribute of the index schema remains as `False`, and so coercion is never attempted. Changing that line as follows
```diff
-index_schema._coerce = True
+index_schema.coerce = True
```
solves the issue.

- [x] I have checked that this issue has not already been reported - I think this is probably the cause of #1131 
- [x] I have confirmed this bug exists on the latest version of pandera.
- [x] (optional) I have confirmed this bug exists on the master branch of pandera.

**Note**: Please read [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) detailing how to provide the necessary information for us to reproduce your bug.

#### Code Sample, a copy-pastable example

```python
import pandas as pd
import pandera as pa


schema = pa.DataFrameSchema(
    {"ColumnOne": pa.Column(float)},
    index=pa.Index(float, name="Index"),
    coerce=True,
)

df = pd.DataFrame(
    {"ColumnOne": [1.0, 2.0]},
    index=pd.Index([1, 2], name="Index"),
)

validated = schema.validate(df)
```

#### Expected behavior
This code should run without error. The index should be coerced from int to float before the validation is run.

#### Desktop (please complete the following information):

 - OS: Windows 10
 - Browser N/A
 - Version N/A



Discussion:
hi @davidbossanyi see this discussion: https://github.com/unionai-oss/pandera/discussions/1134
I am using pandas 1.5.3, but this is still an issue. For a bit of extra context, the code snippet above runs without error with pandas 1.5.3 and pandera 0.13.3, but fails with pandas 1.5.3 and pandera 0.14.5. It also runs without error if I specify `coerce=True` at the index level, i.e.
```python
import pandas as pd
import pandera as pa


schema = pa.DataFrameSchema(
    {"ColumnOne": pa.Column(float)},
    index=pa.Index(float, name="Index", coerce=True),
)

df = pd.DataFrame(
    {"ColumnOne": [1.0, 2.0]},
    index=pd.Index([1, 2], name="Index"),
)

validated = schema.validate(df)
```
The problem is specifically when `coerce=True` is specified at schema level, and it's because coercion is never applied.
ah, cool. please feel free to submit a PR!

### Steps
- see [contributing guide](https://pandera.readthedocs.io/en/stable/CONTRIBUTING.html)
- add the one-liner code change that you mentioned above
- add a unit test (your code example should suffice), probably somewhere in `tests/core/test_schema_components.py`
Will do, hopefully later this week if I get time! Thanks

Resolving patch:
diff --git a/pandera/backends/pandas/container.py b/pandera/backends/pandas/container.py
--- a/pandera/backends/pandas/container.py
+++ b/pandera/backends/pandas/container.py
@@ -449,7 +449,7 @@ def _try_coercion(coerce_fn, obj):
             if schema.coerce:
                 # coercing at the dataframe-level should apply index coercion
                 # for both single- and multi-indexes.
-                index_schema._coerce = True
+                index_schema.coerce = True
             coerced_index = _try_coercion(index_schema.coerce_dtype, obj.index)
             if coerced_index is not None:
                 obj.index = coerced_index


Test patch:
diff --git a/tests/core/test_schema_components.py b/tests/core/test_schema_components.py
--- a/tests/core/test_schema_components.py
+++ b/tests/core/test_schema_components.py
@@ -82,6 +82,15 @@ def test_index_schema_coerce(dtype):
     assert schema.index.dtype.check(validated_index_dtype)
 
 
+@pytest.mark.parametrize("dtype", [Float, Int, String])
+def test_index_schema_coerce_when_coerce_specified_at_schema_level(dtype):
+    """Test that index can be type-coerced when coercion requested at schema level"""
+    schema = DataFrameSchema(index=Index(dtype), coerce=True)
+    df = pd.DataFrame(index=pd.Index([1, 2, 3, 4], dtype="int64"))
+    validated_index_dtype = Engine.dtype(schema(df).index.dtype)
+    assert schema.index.dtype.check(validated_index_dtype)
+
+
 def test_multi_index_columns() -> None:
     """Tests that multi-index Columns within DataFrames validate correctly."""
     schema = DataFrameSchema(