Commit 60c917a
## Summary
Starting from pandas 3.0, two breaking changes caused **all federated
statistics jobs to fail** with `EXECUTION_RESULT_ERROR` on every client:
**Issue 1: `AttributeError: 'StringDtype' object has no attribute
'char'`**
pandas 3.0 enables `future.infer_string` by default, so `pd.read_csv()`
infers string columns as `pd.StringDtype` — a pandas ExtensionDtype that
has no `.char` attribute. This crashed `dtype_to_data_type()` in
`numpy_utils.py` immediately on any DataFrame with string columns.
**Issue 2: `AttributeError: 'Series' object has no attribute 'ravel'`**
`Series.ravel()` was deprecated in pandas 2.2.0 and **removed** in
pandas 3.0. Every `histogram()` method in the statistics module called
`feature.ravel()` on a pandas Series.
Both errors produced empty statistics output `{}` and affected
`df_stats_job`, `df_stats_job_scale`, and `hierarchical_stats` jobs.
## Changes
**Guard / Pin (prevents pandas 3.0 from being installed):**
- Pin `pandas~=2.3` across 16 `requirements.txt` files (15 previously
unpinned + new `df_stats/requirements.txt`)
**Code fixes (forward-compatible with pandas 3.x when pin is eventually
lifted):**
- `nvflare/app_common/statistics/numpy_utils.py` — add `hasattr(dtype,
"char")` guard in `dtype_to_data_type()`; ExtensionDtypes without
`.char` (e.g. `StringDtype`) fall through to `DataType.STRING`
- `nvflare/app_opt/statistics/df/df_core_statistics.py` —
`feature.ravel()` → `feature.to_numpy()`
-
`examples/advanced/federated-statistics/hierarchical_stats/.../hierarchical_stats.py`
— `feature.ravel()` → `feature.to_numpy()`
-
`tests/unit_test/app_common/executors/statistics/mock_df_stats_executor.py`
— `feature.ravel()` → `feature.to_numpy()`
**New file:**
- `examples/advanced/federated-statistics/df_stats/requirements.txt` —
was missing; created from `image_stats/requirements.txt` minus
image-specific deps (`monai`, `kaleido`, `kagglehub`)
**New tests:**
- `tests/unit_test/app_common/statistics/numpy_utils_test.py` — 11 tests
covering all `dtype_to_data_type()` branches including the new
`pd.StringDtype` case
## Test plan
- [ ] All 11 new unit tests in `numpy_utils_test.py` pass
- [ ] Existing `statistics_executor_test.py` tests continue to pass
(histogram path exercises `feature.to_numpy()`)
- [ ] Run `df_stats_job` and `hierarchical_stats` jobs end-to-end with
pandas 2.3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Fixes # .
### Description
A few sentences describing the changes proposed in this pull request.
### Types of changes
<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [ ] New tests added to cover the changes.
- [ ] Quick tests passed locally by running `./runtest.sh`.
- [ ] In-line docstrings updated.
- [ ] Documentation updated.
Co-authored-by: Chester Chen <512707+chesterxgchen@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7886405 commit 60c917a
File tree
22 files changed
+100
-22
lines changed- examples
- advanced
- cifar10/pt/cifar10-sim
- federated-statistics
- df_stats
- hierarchical_stats
- jobs/hierarchical_stats/app/custom
- image_stats
- gnn
- job_api/sklearn
- monai/spleen_ct_segmentation
- psi/user_email_match
- sklearn-kmeans
- sklearn-linear
- sklearn-svm
- vertical_federated_learning/cifar10-splitnn
- xgboost
- hello-world/hello-dp
- tutorials/self-paced-training
- part-4_advanced_federated_learning
- chapter-7_algorithms_and_workflows/07.2_algorithms/07.2.4_split_learning
- chapter-8_federated_LLM_training/08.1_fed_bert
- part-5_federated_learning_applications_in_industries/chapter-11_federated_learning_in_healthcare_lifescience/11.3_medical_devices/code/docker
- nvflare
- app_common/statistics
- app_opt/statistics/df
- tests/unit_test/app_common
- executors/statistics
- statistics
22 files changed
+100
-22
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
108 | | - | |
| 108 | + | |
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
0 commit comments