def test_validate_bool_kwarg(self): arg_names = ['inplace', 'copy'] invalid_values = [1, "True", [1, 2, 3], 5.0] valid_values = [True, False, None] for name in arg_names: for value in invalid_values: with tm.assert_raises_regex( ValueError, "For argument \"%s\" " "expected type bool, " "received type %s" % (name, type(value).__name__)): validate_bool_kwarg(value, name) for value in valid_values: assert validate_bool_kwarg(value, name) == value
def test_validate_bool_kwarg(self): arg_names = ['inplace', 'copy'] invalid_values = [1, "True", [1, 2, 3], 5.0] valid_values = [True, False, None] for name in arg_names: for value in invalid_values: with tm.assertRaisesRegexp(ValueError, ("For argument \"%s\" expected " "type bool, received type %s") % (name, type(value).__name__)): validate_bool_kwarg(value, name) for value in valid_values: tm.assert_equal(validate_bool_kwarg(value, name), value)
def test_validate_bool_kwarg(self): arg_names = ['inplace', 'copy'] invalid_values = [1, "True", [1, 2, 3], 5.0] valid_values = [True, False, None] for name in arg_names: for value in invalid_values: with tm.assertRaisesRegexp(ValueError, ("For argument \"%s\" expected " "type bool, received type %s") % (name, type(value).__name__)): validate_bool_kwarg(value, name) for value in valid_values: assert validate_bool_kwarg(value, name) == value
def consolidate(self, inplace=True): """ Internally consolidate chunks of data Parameters ---------- inplace : boolean, default True Modify the calling object instead of constructing a new one Returns ------- splist : SparseList If inplace=False, new object, otherwise reference to existing object """ inplace = validate_bool_kwarg(inplace, 'inplace') if not inplace: result = self.copy() else: result = self if result.is_consolidated: return result result._consolidate_inplace() return result
def drop_duplicates(self, keep='first', inplace=False): inplace = validate_bool_kwarg(inplace, 'inplace') if isinstance(self, ABCIndexClass): if self.is_unique: return self._shallow_copy() duplicated = self.duplicated(keep=keep) result = self[np.logical_not(duplicated)] if inplace: return self._update_inplace(result) else: return result
def eval(expr, parser='pandas', engine=None, truediv=True, local_dict=None, global_dict=None, resolvers=(), level=0, target=None, inplace=None): """Evaluate a Python expression as a string using various backends. The following arithmetic operations are supported: ``+``, ``-``, ``*``, ``/``, ``**``, ``%``, ``//`` (python engine only) along with the following boolean operations: ``|`` (or), ``&`` (and), and ``~`` (not). Additionally, the ``'pandas'`` parser allows the use of :keyword:`and`, :keyword:`or`, and :keyword:`not` with the same semantics as the corresponding bitwise operators. :class:`~pandas.Series` and :class:`~pandas.DataFrame` objects are supported and behave as they would with plain ol' Python evaluation. Parameters ---------- expr : str or unicode The expression to evaluate. This string cannot contain any Python `statements <http://docs.python.org/2/reference/simple_stmts.html#simple-statements>`__, only Python `expressions <http://docs.python.org/2/reference/simple_stmts.html#expression-statements>`__. parser : string, default 'pandas', {'pandas', 'python'} The parser to use to construct the syntax tree from the expression. The default of ``'pandas'`` parses code slightly different than standard Python. Alternatively, you can parse an expression using the ``'python'`` parser to retain strict Python semantics. See the :ref:`enhancing performance <enhancingperf.eval>` documentation for more details. engine : string or None, default 'numexpr', {'python', 'numexpr'} The engine used to evaluate the expression. Supported engines are - None : tries to use ``numexpr``, falls back to ``python`` - ``'numexpr'``: This default engine evaluates pandas objects using numexpr for large speed ups in complex expressions with large frames. - ``'python'``: Performs operations as if you had ``eval``'d in top level python. This engine is generally not that useful. More backends may be available in the future. truediv : bool, optional Whether to use true division, like in Python >= 3 local_dict : dict or None, optional A dictionary of local variables, taken from locals() by default. global_dict : dict or None, optional A dictionary of global variables, taken from globals() by default. resolvers : list of dict-like or None, optional A list of objects implementing the ``__getitem__`` special method that you can use to inject an additional collection of namespaces to use for variable lookup. For example, this is used in the :meth:`~pandas.DataFrame.query` method to inject the :attr:`~pandas.DataFrame.index` and :attr:`~pandas.DataFrame.columns` variables that refer to their respective :class:`~pandas.DataFrame` instance attributes. level : int, optional The number of prior stack frames to traverse and add to the current scope. Most users will **not** need to change this parameter. target : a target object for assignment, optional, default is None essentially this is a passed in resolver inplace : bool, default True If expression mutates, whether to modify object inplace or return copy with mutation. WARNING: inplace=None currently falls back to to True, but in a future version, will default to False. Use inplace=True explicitly rather than relying on the default. Returns ------- ndarray, numeric scalar, DataFrame, Series Notes ----- The ``dtype`` of any objects involved in an arithmetic ``%`` operation are recursively cast to ``float64``. See the :ref:`enhancing performance <enhancingperf.eval>` documentation for more details. See Also -------- pandas.DataFrame.query pandas.DataFrame.eval """ inplace = validate_bool_kwarg(inplace, 'inplace') first_expr = True if isinstance(expr, string_types): _check_expression(expr) exprs = [e.strip() for e in expr.splitlines() if e.strip() != ''] else: exprs = [expr] multi_line = len(exprs) > 1 if multi_line and target is None: raise ValueError("multi-line expressions are only valid in the " "context of data, use DataFrame.eval") first_expr = True for expr in exprs: expr = _convert_expression(expr) engine = _check_engine(engine) _check_parser(parser) _check_resolvers(resolvers) _check_for_locals(expr, level, parser) # get our (possibly passed-in) scope env = _ensure_scope(level + 1, global_dict=global_dict, local_dict=local_dict, resolvers=resolvers, target=target) parsed_expr = Expr(expr, engine=engine, parser=parser, env=env, truediv=truediv) # construct the engine and evaluate the parsed expression eng = _engines[engine] eng_inst = eng(parsed_expr) ret = eng_inst.evaluate() if parsed_expr.assigner is None and multi_line: raise ValueError("Multi-line expressions are only valid" " if all expressions contain an assignment") # assign if needed if env.target is not None and parsed_expr.assigner is not None: if inplace is None: warnings.warn( "eval expressions containing an assignment currently" "default to operating inplace.\nThis will change in " "a future version of pandas, use inplace=True to " "avoid this warning.", FutureWarning, stacklevel=3) inplace = True # if returning a copy, copy only on the first assignment if not inplace and first_expr: target = env.target.copy() else: target = env.target target[parsed_expr.assigner] = ret if not resolvers: resolvers = ({parsed_expr.assigner: ret}, ) else: # existing resolver needs updated to handle # case of mutating existing column in copy for resolver in resolvers: if parsed_expr.assigner in resolver: resolver[parsed_expr.assigner] = ret break else: resolvers += ({parsed_expr.assigner: ret}, ) ret = None first_expr = False if not inplace and inplace is not None: return target return ret
def eval(expr, parser='pandas', engine=None, truediv=True, local_dict=None, global_dict=None, resolvers=(), level=0, target=None, inplace=None): """Evaluate a Python expression as a string using various backends. The following arithmetic operations are supported: ``+``, ``-``, ``*``, ``/``, ``**``, ``%``, ``//`` (python engine only) along with the following boolean operations: ``|`` (or), ``&`` (and), and ``~`` (not). Additionally, the ``'pandas'`` parser allows the use of :keyword:`and`, :keyword:`or`, and :keyword:`not` with the same semantics as the corresponding bitwise operators. :class:`~pandas.Series` and :class:`~pandas.DataFrame` objects are supported and behave as they would with plain ol' Python evaluation. Parameters ---------- expr : str or unicode The expression to evaluate. This string cannot contain any Python `statements <http://docs.python.org/2/reference/simple_stmts.html#simple-statements>`__, only Python `expressions <http://docs.python.org/2/reference/simple_stmts.html#expression-statements>`__. parser : string, default 'pandas', {'pandas', 'python'} The parser to use to construct the syntax tree from the expression. The default of ``'pandas'`` parses code slightly different than standard Python. Alternatively, you can parse an expression using the ``'python'`` parser to retain strict Python semantics. See the :ref:`enhancing performance <enhancingperf.eval>` documentation for more details. engine : string or None, default 'numexpr', {'python', 'numexpr'} The engine used to evaluate the expression. Supported engines are - None : tries to use ``numexpr``, falls back to ``python`` - ``'numexpr'``: This default engine evaluates pandas objects using numexpr for large speed ups in complex expressions with large frames. - ``'python'``: Performs operations as if you had ``eval``'d in top level python. This engine is generally not that useful. More backends may be available in the future. truediv : bool, optional Whether to use true division, like in Python >= 3 local_dict : dict or None, optional A dictionary of local variables, taken from locals() by default. global_dict : dict or None, optional A dictionary of global variables, taken from globals() by default. resolvers : list of dict-like or None, optional A list of objects implementing the ``__getitem__`` special method that you can use to inject an additional collection of namespaces to use for variable lookup. For example, this is used in the :meth:`~pandas.DataFrame.query` method to inject the :attr:`~pandas.DataFrame.index` and :attr:`~pandas.DataFrame.columns` variables that refer to their respective :class:`~pandas.DataFrame` instance attributes. level : int, optional The number of prior stack frames to traverse and add to the current scope. Most users will **not** need to change this parameter. target : a target object for assignment, optional, default is None essentially this is a passed in resolver inplace : bool, default True If expression mutates, whether to modify object inplace or return copy with mutation. WARNING: inplace=None currently falls back to to True, but in a future version, will default to False. Use inplace=True explicitly rather than relying on the default. Returns ------- ndarray, numeric scalar, DataFrame, Series Notes ----- The ``dtype`` of any objects involved in an arithmetic ``%`` operation are recursively cast to ``float64``. See the :ref:`enhancing performance <enhancingperf.eval>` documentation for more details. See Also -------- pandas.DataFrame.query pandas.DataFrame.eval """ inplace = validate_bool_kwarg(inplace, 'inplace') first_expr = True if isinstance(expr, string_types): _check_expression(expr) exprs = [e.strip() for e in expr.splitlines() if e.strip() != ''] else: exprs = [expr] multi_line = len(exprs) > 1 if multi_line and target is None: raise ValueError("multi-line expressions are only valid in the " "context of data, use DataFrame.eval") first_expr = True for expr in exprs: expr = _convert_expression(expr) engine = _check_engine(engine) _check_parser(parser) _check_resolvers(resolvers) _check_for_locals(expr, level, parser) # get our (possibly passed-in) scope env = _ensure_scope(level + 1, global_dict=global_dict, local_dict=local_dict, resolvers=resolvers, target=target) parsed_expr = Expr(expr, engine=engine, parser=parser, env=env, truediv=truediv) # construct the engine and evaluate the parsed expression eng = _engines[engine] eng_inst = eng(parsed_expr) ret = eng_inst.evaluate() if parsed_expr.assigner is None and multi_line: raise ValueError("Multi-line expressions are only valid" " if all expressions contain an assignment") # assign if needed if env.target is not None and parsed_expr.assigner is not None: if inplace is None: warnings.warn( "eval expressions containing an assignment currently" "default to operating inplace.\nThis will change in " "a future version of pandas, use inplace=True to " "avoid this warning.", FutureWarning, stacklevel=3) inplace = True # if returning a copy, copy only on the first assignment if not inplace and first_expr: target = env.target.copy() else: target = env.target target[parsed_expr.assigner] = ret if not resolvers: resolvers = ({parsed_expr.assigner: ret},) else: # existing resolver needs updated to handle # case of mutating existing column in copy for resolver in resolvers: if parsed_expr.assigner in resolver: resolver[parsed_expr.assigner] = ret break else: resolvers += ({parsed_expr.assigner: ret},) ret = None first_expr = False if not inplace and inplace is not None: return target return ret