Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/array_algos/masked_reductions.py: 32%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

53 statements  

1""" 

2masked_reductions.py is for reduction algorithms using a mask-based approach 

3for missing values. 

4""" 

5 

6from __future__ import annotations 

7 

8from typing import TYPE_CHECKING 

9import warnings 

10 

11import numpy as np 

12 

13from pandas._libs import ( 

14 lib, 

15 missing as libmissing, 

16) 

17 

18from pandas.core.nanops import check_below_min_count 

19 

20if TYPE_CHECKING: 

21 from collections.abc import Callable 

22 

23 from pandas._typing import ( 

24 AxisInt, 

25 npt, 

26 ) 

27 

28 

29def _reductions( 

30 func: Callable, 

31 values: np.ndarray, 

32 mask: npt.NDArray[np.bool_], 

33 *, 

34 skipna: bool = True, 

35 min_count: int = 0, 

36 axis: AxisInt | None = None, 

37 initial: object | lib.NoDefault = lib.no_default, 

38 **kwargs, 

39): 

40 """ 

41 Sum, mean or product for 1D masked array. 

42 

43 Parameters 

44 ---------- 

45 func : np.sum or np.prod 

46 values : np.ndarray 

47 Numpy array with the values (can be of any dtype that support the 

48 operation). 

49 mask : np.ndarray[bool] 

50 Boolean numpy array (True values indicate missing values). 

51 skipna : bool, default True 

52 Whether to skip NA. 

53 min_count : int, default 0 

54 The required number of valid values to perform the operation. If fewer than 

55 ``min_count`` non-NA values are present the result will be NA. 

56 axis : int, optional, default None 

57 initial : scalar, optional 

58 Starting value for the reduction. NumPy has a default value for most 

59 data types, but for object-dtype arrays we need to specify it explicitly 

60 """ 

61 if initial is not lib.no_default: 

62 kwargs["initial"] = initial 

63 

64 if not skipna: 

65 if mask.any() or check_below_min_count(values.shape, None, min_count): 

66 return libmissing.NA 

67 else: 

68 return func(values, axis=axis, **kwargs) 

69 else: 

70 if check_below_min_count(values.shape, mask, min_count) and ( 

71 axis is None or values.ndim == 1 

72 ): 

73 return libmissing.NA 

74 

75 return func(values, where=~mask, axis=axis, **kwargs) 

76 

77 

78def sum( 

79 values: np.ndarray, 

80 mask: npt.NDArray[np.bool_], 

81 *, 

82 skipna: bool = True, 

83 min_count: int = 0, 

84 axis: AxisInt | None = None, 

85 initial: object | lib.NoDefault = lib.no_default, 

86): 

87 return _reductions( 

88 np.sum, 

89 values=values, 

90 mask=mask, 

91 skipna=skipna, 

92 min_count=min_count, 

93 axis=axis, 

94 initial=initial, 

95 ) 

96 

97 

98def prod( 

99 values: np.ndarray, 

100 mask: npt.NDArray[np.bool_], 

101 *, 

102 skipna: bool = True, 

103 min_count: int = 0, 

104 axis: AxisInt | None = None, 

105): 

106 return _reductions( 

107 np.prod, values=values, mask=mask, skipna=skipna, min_count=min_count, axis=axis 

108 ) 

109 

110 

111def _minmax( 

112 func: Callable, 

113 values: np.ndarray, 

114 mask: npt.NDArray[np.bool_], 

115 *, 

116 skipna: bool = True, 

117 axis: AxisInt | None = None, 

118): 

119 """ 

120 Reduction for 1D masked array. 

121 

122 Parameters 

123 ---------- 

124 func : np.min or np.max 

125 values : np.ndarray 

126 Numpy array with the values (can be of any dtype that support the 

127 operation). 

128 mask : np.ndarray[bool] 

129 Boolean numpy array (True values indicate missing values). 

130 skipna : bool, default True 

131 Whether to skip NA. 

132 axis : int, optional, default None 

133 """ 

134 if not skipna: 

135 if mask.any() or not values.size: 

136 # min/max with empty array raise in numpy, pandas returns NA 

137 return libmissing.NA 

138 else: 

139 return func(values, axis=axis) 

140 else: 

141 subset = values[~mask] 

142 if subset.size: 

143 return func(subset, axis=axis) 

144 else: 

145 # min/max with empty array raise in numpy, pandas returns NA 

146 return libmissing.NA 

147 

148 

149def min( 

150 values: np.ndarray, 

151 mask: npt.NDArray[np.bool_], 

152 *, 

153 skipna: bool = True, 

154 axis: AxisInt | None = None, 

155): 

156 return _minmax(np.min, values=values, mask=mask, skipna=skipna, axis=axis) 

157 

158 

159def max( 

160 values: np.ndarray, 

161 mask: npt.NDArray[np.bool_], 

162 *, 

163 skipna: bool = True, 

164 axis: AxisInt | None = None, 

165): 

166 return _minmax(np.max, values=values, mask=mask, skipna=skipna, axis=axis) 

167 

168 

169def mean( 

170 values: np.ndarray, 

171 mask: npt.NDArray[np.bool_], 

172 *, 

173 skipna: bool = True, 

174 axis: AxisInt | None = None, 

175): 

176 if not values.size or mask.all(): 

177 return libmissing.NA 

178 return _reductions(np.mean, values=values, mask=mask, skipna=skipna, axis=axis) 

179 

180 

181def var( 

182 values: np.ndarray, 

183 mask: npt.NDArray[np.bool_], 

184 *, 

185 skipna: bool = True, 

186 axis: AxisInt | None = None, 

187 ddof: int = 1, 

188): 

189 if not values.size or mask.all(): 

190 return libmissing.NA 

191 

192 with warnings.catch_warnings(): 

193 warnings.simplefilter("ignore", RuntimeWarning) 

194 return _reductions( 

195 np.var, values=values, mask=mask, skipna=skipna, axis=axis, ddof=ddof 

196 ) 

197 

198 

199def std( 

200 values: np.ndarray, 

201 mask: npt.NDArray[np.bool_], 

202 *, 

203 skipna: bool = True, 

204 axis: AxisInt | None = None, 

205 ddof: int = 1, 

206): 

207 if not values.size or mask.all(): 

208 return libmissing.NA 

209 

210 with warnings.catch_warnings(): 

211 warnings.simplefilter("ignore", RuntimeWarning) 

212 return _reductions( 

213 np.std, values=values, mask=mask, skipna=skipna, axis=axis, ddof=ddof 

214 )