Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/pandas/compat/numpy/function.py : 56%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2For compatibility with numpy libraries, pandas functions or
3methods have to accept '*args' and '**kwargs' parameters to
4accommodate numpy arguments that are not actually used or
5respected in the pandas implementation.
7To ensure that users do not abuse these parameters, validation
8is performed in 'validators.py' to make sure that any extra
9parameters passed correspond ONLY to those in the numpy signature.
10Part of that validation includes whether or not the user attempted
11to pass in non-default values for these extraneous parameters. As we
12want to discourage users from relying on these parameters when calling
13the pandas implementation, we want them only to pass in the default values
14for these parameters.
16This module provides a set of commonly used default arguments for functions
17and methods that are spread throughout the codebase. This module will make it
18easier to adjust to future upstream changes in the analogous numpy signatures.
19"""
20from collections import OrderedDict
21from distutils.version import LooseVersion
22from typing import Any, Dict, Optional, Union
24from numpy import __version__ as _np_version, ndarray
26from pandas._libs.lib import is_bool, is_integer
27from pandas.errors import UnsupportedFunctionCall
28from pandas.util._validators import (
29 validate_args,
30 validate_args_and_kwargs,
31 validate_kwargs,
32)
35class CompatValidator:
36 def __init__(self, defaults, fname=None, method=None, max_fname_arg_count=None):
37 self.fname = fname
38 self.method = method
39 self.defaults = defaults
40 self.max_fname_arg_count = max_fname_arg_count
42 def __call__(self, args, kwargs, fname=None, max_fname_arg_count=None, method=None):
43 if args or kwargs:
44 fname = self.fname if fname is None else fname
45 max_fname_arg_count = (
46 self.max_fname_arg_count
47 if max_fname_arg_count is None
48 else max_fname_arg_count
49 )
50 method = self.method if method is None else method
52 if method == "args":
53 validate_args(fname, args, max_fname_arg_count, self.defaults)
54 elif method == "kwargs":
55 validate_kwargs(fname, kwargs, self.defaults)
56 elif method == "both":
57 validate_args_and_kwargs(
58 fname, args, kwargs, max_fname_arg_count, self.defaults
59 )
60 else:
61 raise ValueError(f"invalid validation method '{method}'")
64ARGMINMAX_DEFAULTS = dict(out=None)
65validate_argmin = CompatValidator(
66 ARGMINMAX_DEFAULTS, fname="argmin", method="both", max_fname_arg_count=1
67)
68validate_argmax = CompatValidator(
69 ARGMINMAX_DEFAULTS, fname="argmax", method="both", max_fname_arg_count=1
70)
73def process_skipna(skipna, args):
74 if isinstance(skipna, ndarray) or skipna is None:
75 args = (skipna,) + args
76 skipna = True
78 return skipna, args
81def validate_argmin_with_skipna(skipna, args, kwargs):
82 """
83 If 'Series.argmin' is called via the 'numpy' library,
84 the third parameter in its signature is 'out', which
85 takes either an ndarray or 'None', so check if the
86 'skipna' parameter is either an instance of ndarray or
87 is None, since 'skipna' itself should be a boolean
88 """
90 skipna, args = process_skipna(skipna, args)
91 validate_argmin(args, kwargs)
92 return skipna
95def validate_argmax_with_skipna(skipna, args, kwargs):
96 """
97 If 'Series.argmax' is called via the 'numpy' library,
98 the third parameter in its signature is 'out', which
99 takes either an ndarray or 'None', so check if the
100 'skipna' parameter is either an instance of ndarray or
101 is None, since 'skipna' itself should be a boolean
102 """
104 skipna, args = process_skipna(skipna, args)
105 validate_argmax(args, kwargs)
106 return skipna
109ARGSORT_DEFAULTS: "OrderedDict[str, Optional[Union[int, str]]]" = OrderedDict()
110ARGSORT_DEFAULTS["axis"] = -1
111ARGSORT_DEFAULTS["kind"] = "quicksort"
112ARGSORT_DEFAULTS["order"] = None
114if LooseVersion(_np_version) >= LooseVersion("1.17.0"):
115 # GH-26361. NumPy added radix sort and changed default to None.
116 ARGSORT_DEFAULTS["kind"] = None
119validate_argsort = CompatValidator(
120 ARGSORT_DEFAULTS, fname="argsort", max_fname_arg_count=0, method="both"
121)
123# two different signatures of argsort, this second validation
124# for when the `kind` param is supported
125ARGSORT_DEFAULTS_KIND: "OrderedDict[str, Optional[int]]" = OrderedDict()
126ARGSORT_DEFAULTS_KIND["axis"] = -1
127ARGSORT_DEFAULTS_KIND["order"] = None
128validate_argsort_kind = CompatValidator(
129 ARGSORT_DEFAULTS_KIND, fname="argsort", max_fname_arg_count=0, method="both"
130)
133def validate_argsort_with_ascending(ascending, args, kwargs):
134 """
135 If 'Categorical.argsort' is called via the 'numpy' library, the
136 first parameter in its signature is 'axis', which takes either
137 an integer or 'None', so check if the 'ascending' parameter has
138 either integer type or is None, since 'ascending' itself should
139 be a boolean
140 """
142 if is_integer(ascending) or ascending is None:
143 args = (ascending,) + args
144 ascending = True
146 validate_argsort_kind(args, kwargs, max_fname_arg_count=3)
147 return ascending
150CLIP_DEFAULTS = dict(out=None) # type Dict[str, Any]
151validate_clip = CompatValidator(
152 CLIP_DEFAULTS, fname="clip", method="both", max_fname_arg_count=3
153)
156def validate_clip_with_axis(axis, args, kwargs):
157 """
158 If 'NDFrame.clip' is called via the numpy library, the third
159 parameter in its signature is 'out', which can takes an ndarray,
160 so check if the 'axis' parameter is an instance of ndarray, since
161 'axis' itself should either be an integer or None
162 """
164 if isinstance(axis, ndarray):
165 args = (axis,) + args
166 axis = None
168 validate_clip(args, kwargs)
169 return axis
172CUM_FUNC_DEFAULTS: "OrderedDict[str, Any]" = OrderedDict()
173CUM_FUNC_DEFAULTS["dtype"] = None
174CUM_FUNC_DEFAULTS["out"] = None
175validate_cum_func = CompatValidator(
176 CUM_FUNC_DEFAULTS, method="both", max_fname_arg_count=1
177)
178validate_cumsum = CompatValidator(
179 CUM_FUNC_DEFAULTS, fname="cumsum", method="both", max_fname_arg_count=1
180)
183def validate_cum_func_with_skipna(skipna, args, kwargs, name):
184 """
185 If this function is called via the 'numpy' library, the third
186 parameter in its signature is 'dtype', which takes either a
187 'numpy' dtype or 'None', so check if the 'skipna' parameter is
188 a boolean or not
189 """
190 if not is_bool(skipna):
191 args = (skipna,) + args
192 skipna = True
194 validate_cum_func(args, kwargs, fname=name)
195 return skipna
198ALLANY_DEFAULTS: "OrderedDict[str, Optional[bool]]" = OrderedDict()
199ALLANY_DEFAULTS["dtype"] = None
200ALLANY_DEFAULTS["out"] = None
201ALLANY_DEFAULTS["keepdims"] = False
202validate_all = CompatValidator(
203 ALLANY_DEFAULTS, fname="all", method="both", max_fname_arg_count=1
204)
205validate_any = CompatValidator(
206 ALLANY_DEFAULTS, fname="any", method="both", max_fname_arg_count=1
207)
209LOGICAL_FUNC_DEFAULTS = dict(out=None, keepdims=False)
210validate_logical_func = CompatValidator(LOGICAL_FUNC_DEFAULTS, method="kwargs")
212MINMAX_DEFAULTS = dict(axis=None, out=None, keepdims=False)
213validate_min = CompatValidator(
214 MINMAX_DEFAULTS, fname="min", method="both", max_fname_arg_count=1
215)
216validate_max = CompatValidator(
217 MINMAX_DEFAULTS, fname="max", method="both", max_fname_arg_count=1
218)
220RESHAPE_DEFAULTS: Dict[str, str] = dict(order="C")
221validate_reshape = CompatValidator(
222 RESHAPE_DEFAULTS, fname="reshape", method="both", max_fname_arg_count=1
223)
225REPEAT_DEFAULTS: Dict[str, Any] = dict(axis=None)
226validate_repeat = CompatValidator(
227 REPEAT_DEFAULTS, fname="repeat", method="both", max_fname_arg_count=1
228)
230ROUND_DEFAULTS: Dict[str, Any] = dict(out=None)
231validate_round = CompatValidator(
232 ROUND_DEFAULTS, fname="round", method="both", max_fname_arg_count=1
233)
235SORT_DEFAULTS: "OrderedDict[str, Optional[Union[int, str]]]" = OrderedDict()
236SORT_DEFAULTS["axis"] = -1
237SORT_DEFAULTS["kind"] = "quicksort"
238SORT_DEFAULTS["order"] = None
239validate_sort = CompatValidator(SORT_DEFAULTS, fname="sort", method="kwargs")
241STAT_FUNC_DEFAULTS: "OrderedDict[str, Optional[Any]]" = OrderedDict()
242STAT_FUNC_DEFAULTS["dtype"] = None
243STAT_FUNC_DEFAULTS["out"] = None
245PROD_DEFAULTS = SUM_DEFAULTS = STAT_FUNC_DEFAULTS.copy()
246SUM_DEFAULTS["keepdims"] = False
247SUM_DEFAULTS["initial"] = None
249MEDIAN_DEFAULTS = STAT_FUNC_DEFAULTS.copy()
250MEDIAN_DEFAULTS["overwrite_input"] = False
251MEDIAN_DEFAULTS["keepdims"] = False
253STAT_FUNC_DEFAULTS["keepdims"] = False
255validate_stat_func = CompatValidator(STAT_FUNC_DEFAULTS, method="kwargs")
256validate_sum = CompatValidator(
257 SUM_DEFAULTS, fname="sum", method="both", max_fname_arg_count=1
258)
259validate_prod = CompatValidator(
260 PROD_DEFAULTS, fname="prod", method="both", max_fname_arg_count=1
261)
262validate_mean = CompatValidator(
263 STAT_FUNC_DEFAULTS, fname="mean", method="both", max_fname_arg_count=1
264)
265validate_median = CompatValidator(
266 MEDIAN_DEFAULTS, fname="median", method="both", max_fname_arg_count=1
267)
269STAT_DDOF_FUNC_DEFAULTS: "OrderedDict[str, Optional[bool]]" = OrderedDict()
270STAT_DDOF_FUNC_DEFAULTS["dtype"] = None
271STAT_DDOF_FUNC_DEFAULTS["out"] = None
272STAT_DDOF_FUNC_DEFAULTS["keepdims"] = False
273validate_stat_ddof_func = CompatValidator(STAT_DDOF_FUNC_DEFAULTS, method="kwargs")
275TAKE_DEFAULTS: "OrderedDict[str, Optional[str]]" = OrderedDict()
276TAKE_DEFAULTS["out"] = None
277TAKE_DEFAULTS["mode"] = "raise"
278validate_take = CompatValidator(TAKE_DEFAULTS, fname="take", method="kwargs")
281def validate_take_with_convert(convert, args, kwargs):
282 """
283 If this function is called via the 'numpy' library, the third
284 parameter in its signature is 'axis', which takes either an
285 ndarray or 'None', so check if the 'convert' parameter is either
286 an instance of ndarray or is None
287 """
289 if isinstance(convert, ndarray) or convert is None:
290 args = (convert,) + args
291 convert = True
293 validate_take(args, kwargs, max_fname_arg_count=3, method="both")
294 return convert
297TRANSPOSE_DEFAULTS = dict(axes=None)
298validate_transpose = CompatValidator(
299 TRANSPOSE_DEFAULTS, fname="transpose", method="both", max_fname_arg_count=0
300)
303def validate_window_func(name, args, kwargs):
304 numpy_args = ("axis", "dtype", "out")
305 msg = (
306 f"numpy operations are not valid with window objects. "
307 f"Use .{name}() directly instead "
308 )
310 if len(args) > 0:
311 raise UnsupportedFunctionCall(msg)
313 for arg in numpy_args:
314 if arg in kwargs:
315 raise UnsupportedFunctionCall(msg)
318def validate_rolling_func(name, args, kwargs):
319 numpy_args = ("axis", "dtype", "out")
320 msg = (
321 f"numpy operations are not valid with window objects. "
322 f"Use .rolling(...).{name}() instead "
323 )
325 if len(args) > 0:
326 raise UnsupportedFunctionCall(msg)
328 for arg in numpy_args:
329 if arg in kwargs:
330 raise UnsupportedFunctionCall(msg)
333def validate_expanding_func(name, args, kwargs):
334 numpy_args = ("axis", "dtype", "out")
335 msg = (
336 f"numpy operations are not valid with window objects. "
337 f"Use .expanding(...).{name}() instead "
338 )
340 if len(args) > 0:
341 raise UnsupportedFunctionCall(msg)
343 for arg in numpy_args:
344 if arg in kwargs:
345 raise UnsupportedFunctionCall(msg)
348def validate_groupby_func(name, args, kwargs, allowed=None):
349 """
350 'args' and 'kwargs' should be empty, except for allowed
351 kwargs because all of
352 their necessary parameters are explicitly listed in
353 the function signature
354 """
355 if allowed is None:
356 allowed = []
358 kwargs = set(kwargs) - set(allowed)
360 if len(args) + len(kwargs) > 0:
361 raise UnsupportedFunctionCall(
362 f"numpy operations are not valid with "
363 f"groupby. Use .groupby(...).{name}() "
364 f"instead"
365 )
368RESAMPLER_NUMPY_OPS = ("min", "max", "sum", "prod", "mean", "std", "var")
371def validate_resampler_func(method, args, kwargs):
372 """
373 'args' and 'kwargs' should be empty because all of
374 their necessary parameters are explicitly listed in
375 the function signature
376 """
377 if len(args) + len(kwargs) > 0:
378 if method in RESAMPLER_NUMPY_OPS:
379 raise UnsupportedFunctionCall(
380 f"numpy operations are not "
381 f"valid with resample. Use "
382 f".resample(...).{method}() instead"
383 )
384 else:
385 raise TypeError("too many arguments passed in")
388def validate_minmax_axis(axis):
389 """
390 Ensure that the axis argument passed to min, max, argmin, or argmax is
391 zero or None, as otherwise it will be incorrectly ignored.
393 Parameters
394 ----------
395 axis : int or None
397 Raises
398 ------
399 ValueError
400 """
401 ndim = 1 # hard-coded for Index
402 if axis is None:
403 return
404 if axis >= ndim or (axis < 0 and ndim + axis < 0):
405 raise ValueError(f"`axis` must be fewer than the number of dimensions ({ndim})")