This is an automated email from the ASF dual-hosted git repository.
shunping pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new fa6e901a905 [Python] Fix DataFrame Series.value_counts with bins
(#40505)
fa6e901a905 is described below
commit fa6e901a905d81fdb013341854e9ad7095eaa260
Author: Anish Mehta <[email protected]>
AuthorDate: Tue Oct 13 19:21:13 2026 +0530
[Python] Fix DataFrame Series.value_counts with bins (#40505)
---
CHANGES.md | 1 +
sdks/python/apache_beam/dataframe/frames.py | 9 ++++++++-
sdks/python/apache_beam/dataframe/frames_test.py | 9 +++++++++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/CHANGES.md b/CHANGES.md
index fda4c9edc21..d1910513da5 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -104,6 +104,7 @@
* (Python) `Duration` built from float seconds now rounds to the nearest
microsecond instead of truncating, which could lose a microsecond
([#40263](https://github.com/apache/beam/issues/40263)).
* (Python) `ReadFromText` with `escapechar` no longer skips a delimiter that
directly follows an escaped delimiter, which merged two records into one
([#40459](https://github.com/apache/beam/issues/40459)).
* (Python) DataFrame API: `agg` with a list that includes `'count'` or
`'size'` now labels those rows `count`/`size` instead of `sum`
([#40504](https://github.com/apache/beam/issues/40504)).
+* (Python) DataFrame API: `Series.value_counts(bins=...)` no longer always
fails with a `TypeError`
([#40503](https://github.com/apache/beam/issues/40503)).
* Fixed X (Java/Python) ([#X](https://github.com/apache/beam/issues/X)).
## Security Fixes
diff --git a/sdks/python/apache_beam/dataframe/frames.py
b/sdks/python/apache_beam/dataframe/frames.py
index ea634beadee..500152f4490 100644
--- a/sdks/python/apache_beam/dataframe/frames.py
+++ b/sdks/python/apache_beam/dataframe/frames.py
@@ -2345,11 +2345,18 @@ class DeferredSeries(DeferredDataFrameOrSeries):
reason="order-sensitive")
if bins is not None:
+ # pandas can't compute bins for the empty proxy, so make the proxy from
+ # a single element of the same type.
+ proxy = self._expr.proxy()
+ proxy = pd.Series([0], dtype=proxy.dtype, name=proxy.name).value_counts(
+ normalize=normalize, bins=bins, dropna=dropna)[:0]
return frame_base.DeferredFrame.wrap(
expressions.ComputedExpression(
'value_counts',
lambda s: s.value_counts(
- normalize=normalize, bins=bins, dropna=dropna)[self._expr],
+ normalize=normalize, bins=bins, dropna=dropna),
+ [self._expr],
+ proxy=proxy,
requires_partition_by=partitionings.Singleton(
reason=(
"value_counts with bin specified requires collecting "
diff --git a/sdks/python/apache_beam/dataframe/frames_test.py
b/sdks/python/apache_beam/dataframe/frames_test.py
index 41f3a913fb7..67f61aa68c6 100644
--- a/sdks/python/apache_beam/dataframe/frames_test.py
+++ b/sdks/python/apache_beam/dataframe/frames_test.py
@@ -796,6 +796,15 @@ class DeferredFrameTest(_AbstractFrameTest):
value_counts(dropna=dropna, normalize=normalize),
df)
+ def test_series_value_counts_with_bins(self):
+ s = pd.Series([1, 2, 2, 3, 5, 8, 8, 9, np.nan])
+
+ self._run_test(lambda s: s.value_counts(bins=3), s, nonparallel=True)
+ self._run_test(
+ lambda s: s.value_counts(bins=3, normalize=True), s, nonparallel=True)
+ self._run_test(
+ lambda s: s.value_counts(bins=[0, 5, 10]), s, nonparallel=True)
+
def test_value_counts_does_not_support_sort(self):
df = pd.DataFrame({
'num_legs': [2, 4, 4, 6, np.nan, np.nan],