Ejemplo n.º 1
0
    def _create_comparison_method(cls, op):
        op_name = op.__name__

        #print(op_name)
        def cmp_method(self, other):
            if is_list_like(other):
                other = cls._from_sequence(other)

            if other.ndim > 0 and len(self) != len(other):
                raise ValueError("Lengths must match to compare")

            if op_name == 'eq':
                return SparseExtensionArray(self.data == other.data)
            if op_name == 'ne':
                return SparseExtensionArray(self.data != other.data)
            if op_name == 'lt':
                return SparseExtensionArray(self.data < other.data)
            if op_name == 'gt':
                return SparseExtensionArray(self.data > other.data)
            if op_name == 'le':
                return SparseExtensionArray(self.data <= other.data)
            if op_name == 'ge':
                return SparseExtensionArray(self.data >= other.data)

        opname = ops._get_op_name(op, True)
        return set_function_name(cmp_method, opname, cls)
    def _create_method(cls, op, coerce_to_dtype=True, result_dtype=None):
        # NOTE: this overrides, but coerce_to_dtype, result_dtype might not be needed

        def _binop(self, other):
            lvalues = self._tensor

            if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
                # Rely on pandas to unbox and dispatch to us.
                return NotImplemented

            # divmod returns a tuple
            if op_name in ["__divmod__", "__rdivmod__"]:
                # TODO: return tuple
                # div, mod = result
                raise NotImplementedError

            if isinstance(other, (TensorArray, TensorElement)):
                rvalues = other._tensor
            else:
                rvalues = other

            result = op(lvalues, rvalues)

            # Force a TensorArray if rvalue is not a scalar
            if isinstance(self, TensorElement) and \
                    (not isinstance(other, TensorElement) or not np.isscalar(other)):
                result_wrapped = TensorArray(result)
            else:
                result_wrapped = cls(result)

            return result_wrapped

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)
Ejemplo n.º 3
0
    def _create_method(cls, op, coerce_to_dtype=True):
        """
        A class method that returns a method that will correspond to an
        operator for an ExtensionArray subclass, by dispatching to the
        relevant operator defined on the individual elements of the
        ExtensionArray.

        Parameters
        ----------
        op : function
            An operator that takes arguments op(a, b)
        coerce_to_dtype :  bool
            boolean indicating whether to attempt to convert
            the result to the underlying ExtensionArray dtype
            (default True)

        Returns
        -------
        A method that can be bound to a method of a class

        Example
        -------
        Given an ExtensionArray subclass called MyExtensionArray, use

        >>> __add__ = cls._create_method(operator.add)

        in the class definition of MyExtensionArray to create the operator
        for addition, that will be based on the operator implementation
        of the underlying elements of the ExtensionArray

        """
        def _binop(self, other):
            def convert_values(param):
                if isinstance(param, ExtensionArray) or is_list_like(param):
                    ovalues = param
                else:  # Assume its an object
                    ovalues = [param] * len(self)
                return ovalues

            lvalues = self
            rvalues = convert_values(other)

            # If the operator is not defined for the underlying objects,
            # a TypeError should be raised
            res = [op(a, b) for (a, b) in zip(lvalues, rvalues)]

            if coerce_to_dtype:
                try:
                    res = self._from_sequence(res)
                except TypeError:
                    pass

            return res

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)
Ejemplo n.º 4
0
    def _create_method(cls, op, coerce_to_dtype=True):
        """
        A class method that returns a method that will correspond to an
        operator for an ExtensionArray subclass, by dispatching to the
        relevant operator defined on the individual elements of the
        ExtensionArray.

        Parameters
        ----------
        op : function
            An operator that takes arguments op(a, b)
        coerce_to_dtype :  bool
            boolean indicating whether to attempt to convert
            the result to the underlying ExtensionArray dtype
            (default True)

        Returns
        -------
        A method that can be bound to a method of a class

        Example
        -------
        Given an ExtensionArray subclass called MyExtensionArray, use

        >>> __add__ = cls._create_method(operator.add)

        in the class definition of MyExtensionArray to create the operator
        for addition, that will be based on the operator implementation
        of the underlying elements of the ExtensionArray

        """

        def _binop(self, other):
            def convert_values(param):
                if isinstance(param, ExtensionArray) or is_list_like(param):
                    ovalues = param
                else:  # Assume its an object
                    ovalues = [param] * len(self)
                return ovalues
            lvalues = self
            rvalues = convert_values(other)

            # If the operator is not defined for the underlying objects,
            # a TypeError should be raised
            res = [op(a, b) for (a, b) in zip(lvalues, rvalues)]

            if coerce_to_dtype:
                try:
                    res = self._from_sequence(res)
                except TypeError:
                    pass

            return res

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)
Ejemplo n.º 5
0
    def _create_method(cls, op, coerce_to_dtype=True):
        # NOTE: this overrides, but coerce_to_dtype might not be needed

        def _binop(self, other):
            lvalues = self._tensor
            rvalues = other._tensor if isinstance(other,
                                                  TensorArray) else other
            res = op(lvalues, rvalues)
            return TensorArray(res)

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)
Ejemplo n.º 6
0
    def _create_arithmetic_method(cls, op):
        #print('op name: %s' % op.__name__)
        def sparse_arithmetic_method(self, other):
            op_name = op.__name__
            if op_name == 'add':
                coords, data = _sum(self.data.coords[0], self.data.data,
                                    other.values.data.coords[0],
                                    other.values.data.data)
                coo = sparse.COO(coords, data, shape=self.shape)
                return SparseExtensionArray(coo)

        opname = ops._get_op_name(op, True)
        return set_function_name(sparse_arithmetic_method, opname, cls)
Ejemplo n.º 7
0
    def _create_method(cls, op, coerce_to_dtype=True):
        """
        A class method that returns a method that will correspond to an
        operator for an ExtensionArray subclass, by dispatching to the
        relevant operator defined on the individual elements of the
        ExtensionArray.

        Parameters
        ----------
        op : function
            An operator that takes arguments op(a, b)
        coerce_to_dtype :  bool, default True
            boolean indicating whether to attempt to convert
            the result to the underlying ExtensionArray dtype.
            If it's not possible to create a new ExtensionArray with the
            values, an ndarray is returned instead.

        Returns
        -------
        Callable[[Any, Any], Union[ndarray, ExtensionArray]]
            A method that can be bound to a class. When used, the method
            receives the two arguments, one of which is the instance of
            this class, and should return an ExtensionArray or an ndarray.

            Returning an ndarray may be necessary when the result of the
            `op` cannot be stored in the ExtensionArray. The dtype of the
            ndarray uses NumPy's normal inference rules.

        Examples
        --------
        Given an ExtensionArray subclass called MyExtensionArray, use

        >>> __add__ = cls._create_method(operator.add)

        in the class definition of MyExtensionArray to create the operator
        for addition, that will be based on the operator implementation
        of the underlying elements of the ExtensionArray
        """
        def _binop(self, other):
            def convert_values(param):
                if isinstance(param, ExtensionArray) or is_list_like(param):
                    ovalues = param
                else:  # Assume its an object
                    ovalues = [param] * len(self)
                return ovalues

            if isinstance(other, (ABCSeries, ABCIndexClass)):
                # rely on qq_pandas to unbox and dispatch to us
                return NotImplemented

            lvalues = self
            rvalues = convert_values(other)

            # If the operator is not defined for the underlying objects,
            # a TypeError should be raised
            res = [op(a, b) for (a, b) in zip(lvalues, rvalues)]

            def _maybe_convert(arr):
                if coerce_to_dtype:
                    # https://github.com/pandas-dev/pandas/issues/22850
                    # We catch all regular exceptions here, and fall back
                    # to an ndarray.
                    try:
                        res = self._from_sequence(arr)
                    except Exception:
                        res = np.asarray(arr)
                else:
                    res = np.asarray(arr)
                return res

            if op.__name__ in {"divmod", "rdivmod"}:
                a, b = zip(*res)
                res = _maybe_convert(a), _maybe_convert(b)
            else:
                res = _maybe_convert(res)
            return res

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)
Ejemplo n.º 8
0
    def _create_method(cls, op, coerce_to_dtype=True):
        """
        A class method that returns a method that will correspond to an
        operator for an ExtensionArray subclass, by dispatching to the
        relevant operator defined on the individual elements of the
        ExtensionArray.
        Parameters
        ----------
        op : function
            An operator that takes arguments op(a, b)
        coerce_to_dtype :  bool
            boolean indicating whether to attempt to convert
            the result to the underlying ExtensionArray dtype
            (default True)
        Returns
        -------
        A method that can be bound to a method of a class
        Example
        -------
        Given an ExtensionArray subclass called MyExtensionArray, use
        >>> __add__ = cls._create_method(operator.add)
        in the class definition of MyExtensionArray to create the operator
        for addition, that will be based on the operator implementation
        of the underlying elements of the ExtensionArray
        """

        def _binop(self, other):
            def validate_length(obj1, obj2):
                # validates length and converts to listlike
                try:
                    if len(obj1) == len(obj2):
                        return obj2
                    else:
                        raise ValueError("Lengths must match")
                except TypeError:
                    return [obj2] * len(obj1)

            def convert_values(param):
                # convert to a quantity or listlike
                if isinstance(param, cls):
                    return param.quantity
                elif isinstance(param, _Quantity):
                    return param
                elif is_list_like(param) and isinstance(param[0], _Quantity):
                    return type(param[0])([p.magnitude for p in param], param[0].units)
                else:
                    return param

            if isinstance(other, Series):
                return NotImplemented
            lvalues = self.quantity
            other = validate_length(lvalues, other)
            rvalues = convert_values(other)
            # Pint quantities may only be exponented by single values, not arrays.
            # Reduce single value arrays to single value to allow power ops
            if isinstance(rvalues, _Quantity):
                if len(set(np.array(rvalues.data))) == 1:
                    rvalues = rvalues[0]
            elif len(set(np.array(rvalues))) == 1:
                rvalues = rvalues[0]
            # If the operator is not defined for the underlying objects,
            # a TypeError should be raised
            res = op(lvalues, rvalues)

            if op.__name__ == "divmod":
                return (
                    cls.from_1darray_quantity(res[0]),
                    cls.from_1darray_quantity(res[1]),
                )

            if coerce_to_dtype:
                try:
                    res = cls.from_1darray_quantity(res)
                except TypeError:
                    pass

            return res

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)
Ejemplo n.º 9
0
    def _create_method(cls, op, coerce_to_dtype=True):
        """
        A class method that returns a method that will correspond to an
        operator for an ExtensionArray subclass, by dispatching to the
        relevant operator defined on the individual elements of the
        ExtensionArray.

        Parameters
        ----------
        op : function
            An operator that takes arguments op(a, b)
        coerce_to_dtype :  bool, default True
            boolean indicating whether to attempt to convert
            the result to the underlying ExtensionArray dtype.
            If it's not possible to create a new ExtensionArray with the
            values, an ndarray is returned instead.

        Returns
        -------
        Callable[[Any, Any], Union[ndarray, ExtensionArray]]
            A method that can be bound to a class. When used, the method
            receives the two arguments, one of which is the instance of
            this class, and should return an ExtensionArray or an ndarray.

            Returning an ndarray may be necessary when the result of the
            `op` cannot be stored in the ExtensionArray. The dtype of the
            ndarray uses NumPy's normal inference rules.

        Example
        -------
        Given an ExtensionArray subclass called MyExtensionArray, use

        >>> __add__ = cls._create_method(operator.add)

        in the class definition of MyExtensionArray to create the operator
        for addition, that will be based on the operator implementation
        of the underlying elements of the ExtensionArray
        """

        def _binop(self, other):
            def convert_values(param):
                if isinstance(param, ExtensionArray) or is_list_like(param):
                    ovalues = param
                else:  # Assume its an object
                    ovalues = [param] * len(self)
                return ovalues
            lvalues = self
            rvalues = convert_values(other)

            # If the operator is not defined for the underlying objects,
            # a TypeError should be raised
            res = [op(a, b) for (a, b) in zip(lvalues, rvalues)]

            def _maybe_convert(arr):
                if coerce_to_dtype:
                    # https://github.com/pandas-dev/pandas/issues/22850
                    # We catch all regular exceptions here, and fall back
                    # to an ndarray.
                    try:
                        res = self._from_sequence(arr)
                    except Exception:
                        res = np.asarray(arr)
                else:
                    res = np.asarray(arr)
                return res

            if op.__name__ in {'divmod', 'rdivmod'}:
                a, b = zip(*res)
                res = _maybe_convert(a), _maybe_convert(b)
            else:
                res = _maybe_convert(res)
            return res

        op_name = ops._get_op_name(op, True)
        return set_function_name(_binop, op_name, cls)