@@ -159,6 +159,7 @@ def __init__(self, kind: str, how: str, has_dropped_na: bool) -> None:
159
159
"sum" ,
160
160
"ohlc" ,
161
161
"cumsum" ,
162
+ "prod" ,
162
163
}
163
164
164
165
_cython_arity = {"ohlc" : 4 } # OHLC
@@ -221,13 +222,13 @@ def _get_cython_vals(self, values: np.ndarray) -> np.ndarray:
221
222
values = ensure_float64 (values )
222
223
223
224
elif values .dtype .kind in ["i" , "u" ]:
224
- if how in ["var" , "prod" , " mean" ] or (
225
+ if how in ["var" , "mean" ] or (
225
226
self .kind == "transform" and self .has_dropped_na
226
227
):
227
228
# result may still include NaN, so we have to cast
228
229
values = ensure_float64 (values )
229
230
230
- elif how in ["sum" , "ohlc" , "cumsum" ]:
231
+ elif how in ["sum" , "ohlc" , "prod" , " cumsum" ]:
231
232
# Avoid overflow during group op
232
233
if values .dtype .kind == "i" :
233
234
values = ensure_int64 (values )
@@ -597,8 +598,16 @@ def _call_cython_op(
597
598
min_count = min_count ,
598
599
is_datetimelike = is_datetimelike ,
599
600
)
600
- elif self .how == "ohlc" :
601
- func (result , counts , values , comp_ids , min_count , mask , result_mask )
601
+ elif self .how in ["ohlc" , "prod" ]:
602
+ func (
603
+ result ,
604
+ counts ,
605
+ values ,
606
+ comp_ids ,
607
+ min_count = min_count ,
608
+ mask = mask ,
609
+ result_mask = result_mask ,
610
+ )
602
611
else :
603
612
func (result , counts , values , comp_ids , min_count , ** kwargs )
604
613
else :
@@ -631,8 +640,8 @@ def _call_cython_op(
631
640
# need to have the result set to np.nan, which may require casting,
632
641
# see GH#40767
633
642
if is_integer_dtype (result .dtype ) and not is_datetimelike :
634
- # Neutral value for sum is 0, so don't fill empty groups with nan
635
- cutoff = max (0 if self .how == "sum" else 1 , min_count )
643
+ # if the op keeps the int dtypes, we have to use 0
644
+ cutoff = max (0 if self .how in [ "sum" , "prod" ] else 1 , min_count )
636
645
empty_groups = counts < cutoff
637
646
if empty_groups .any ():
638
647
if result_mask is not None and self .uses_mask ():
0 commit comments