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],

Reply via email to