def concurrent_dict_pop_ovld(self, key, default=None): if not isinstance(self, ConcurrentDictType): return None _func_name = f'Method {self}::pop()' ty_checker = TypeChecker(_func_name) # default value is expected to be of the same (or safely casted) type as dict's value_type no_default = isinstance(default, (types.NoneType, types.Omitted)) or default is None default_is_optional = isinstance(default, types.Optional) if not (no_default or check_types_comparable(default, self.value_type) or default_is_optional and check_types_comparable(default.type, self.value_type)): ty_checker.raise_exc(default, f'{self.value_type} or convertible or None', 'default') dict_key_type, dict_value_type = self.key_type, self.value_type cast_key = key is not dict_key_type def concurrent_dict_pop_impl(self, key, default=None): _key = key if cast_key == False else _cast(key, dict_key_type) # noqa found, res = hashmap_pop(self, _key) if not found: if no_default == False: # noqa return _cast(default, dict_value_type) else: return None return res return concurrent_dict_pop_impl
def sdc_pandas_series_operator_binop(self, other): """ Pandas Series operator :attr:`pandas.Series.binop` implementation Note: Currently implemented for numeric Series only. Differs from Pandas in returning Series with fixed dtype :obj:`float64` .. only:: developer **Test**: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op1* python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op2* python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_operator_binop* Parameters ---------- series: :obj:`pandas.Series` Input series other: :obj:`pandas.Series` or :obj:`scalar` Series or scalar value to be used as a second argument of binary operation Returns ------- :obj:`pandas.Series` The result of the operation """ _func_name = 'Method comp_binop().' ty_checker = TypeChecker(_func_name) self_is_series, other_is_series = isinstance(self, SeriesType), isinstance(other, SeriesType) if not (self_is_series or other_is_series): return None # this overload is not for string series self_is_string_series = self_is_series and isinstance(self.dtype, types.UnicodeType) other_is_string_series = other_is_series and isinstance(other.dtype, types.UnicodeType) if self_is_string_series or other_is_string_series: return None if not isinstance(self, (SeriesType, types.Number)): ty_checker.raise_exc(self, 'pandas.series or scalar', 'self') if not isinstance(other, (SeriesType, types.Number)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: series_indexes_comparable = check_types_comparable(self.index, other.index) if not series_indexes_comparable: raise TypingError('{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format(_func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) def series_operator_binop_wrapper(self, other): return sdc_binop(self, other) return series_operator_binop_wrapper
def sdc_pandas_series_operator_comp_binop(self, other): """ Pandas Series operator :attr:`pandas.Series.comp_binop` implementation .. only:: developer **Test**: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op7* python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_operator_comp_binop* Parameters ---------- series: :obj:`pandas.Series` Input series other: :obj:`pandas.Series` or :obj:`scalar` Series or scalar value to be used as a second argument of binary operation Returns ------- :obj:`pandas.Series` The result of the operation """ _func_name = 'Operator comp_binop().' ty_checker = TypeChecker(_func_name) self_is_series, other_is_series = isinstance(self, SeriesType), isinstance( other, SeriesType) if not (self_is_series or other_is_series): return None if not isinstance(self, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(self, 'pandas.series or scalar', 'self') if not isinstance(other, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: none_or_numeric_indexes = ((isinstance(self.index, types.NoneType) or check_index_is_numeric(self)) and (isinstance(other.index, types.NoneType) or check_index_is_numeric(other))) series_indexes_comparable = check_types_comparable( self.index, other.index) or none_or_numeric_indexes if not series_indexes_comparable: raise TypingError( '{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format( _func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) def sdc_pandas_series_operator_comp_binop_impl(self, other): return self.comp_binop(other) return sdc_pandas_series_operator_comp_binop_impl
def pd_range_index_equals_overload(self, other): if not isinstance(self, RangeIndexType): return None _func_name = 'Method equals().' if not isinstance(other, sdc_pandas_index_types): raise SDCLimitation( f"{_func_name} Unsupported parameter. Given 'other': {other}") if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) if isinstance(other, sdc_indexes_range_like): def pd_range_index_equals_impl(self, other): if len(self) != len(other): return False if len(self) == 0: return True if len(self) == 1: return self.start == other.start return self.start == other.start and self.step == other.step else: def pd_range_index_equals_impl(self, other): return sdc_numeric_indexes_equals(self, other) return pd_range_index_equals_impl
def pd_int64_index_append_overload(self, other): if not isinstance(self, Int64IndexType): return None _func_name = 'Method append().' ty_checker = TypeChecker(_func_name) if not isinstance(other, sdc_pandas_index_types): ty_checker.raise_exc(other, 'pandas index', 'other') if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) convert_other = not isinstance(other, types.Array) _, res_index_dtype = find_index_common_dtype(self, other) return_as_array_index = res_index_dtype is not types.int64 def pd_int64_index_append_impl(self, other): _other = other.values if convert_other == True else other # noqa new_index_data = hpat_arrays_append(self._data, _other) # this is only needed while some indexes are represented with arrays # TO-DO: support pd.Index() overload with dtype arg to create indexes if return_as_array_index == False: # noqa return pd.Int64Index(new_index_data) else: return new_index_data return pd_int64_index_append_impl
def pd_positional_index_reindex_overload(self, target, method=None, level=None, limit=None, tolerance=None): if not isinstance(self, PositionalIndexType): return None _func_name = 'Method reindex().' if not isinstance(target, sdc_pandas_index_types): raise SDCLimitation( f"{_func_name} Unsupported parameter. Given 'target': {target}") if not check_types_comparable(self, target): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, target={}'.format(_func_name, self, target)) def pd_positional_index_reindex_impl(self, target, method=None, level=None, limit=None, tolerance=None): return sdc_indexes_reindex(self, target=target, method=method, level=level, tolerance=tolerance) return pd_positional_index_reindex_impl
def pd_positional_index_ne_overload(self, other): _func_name = 'Operator ne.' if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) self_is_positional_index = isinstance(self, PositionalIndexType) other_is_positional_index = isinstance(other, PositionalIndexType) possible_arg_types = (types.Array, types.Number) + sdc_pandas_index_types if not ( self_is_positional_index and other_is_positional_index or (self_is_positional_index and isinstance(other, possible_arg_types)) or (isinstance(self, possible_arg_types) and other_is_positional_index)): return None def pd_positional_index_ne_impl(self, other): eq_res = np.asarray( self == other) # FIXME_Numba#5157: remove np.asarray and return as list return list(~eq_res) return pd_positional_index_ne_impl
def sdc_array_equal_overload(A, B): """ Checks 1D sequences A and B of comparable dtypes are equal """ if not (isinstance( A, (types.Array, StringArrayType, types.NoneType, RangeIndexType)) or isinstance(B, (types.Array, StringArrayType, types.NoneType, RangeIndexType))): return None _func_name = "numpy-like 'array_equal'" if not check_types_comparable(A, B): msg = '{} Not comparable arguments. Given: A={}, B={}' raise TypingError(msg.format(_func_name, A, B)) if (A == string_array_type and A == B): def sdc_array_equal_str_arr_impl(A, B): is_index_equal = (len(A) == len(B) and num_total_chars(A) == num_total_chars(B)) for i in numpy.arange(len(A)): if (A[i] != B[i] or str_arr_is_na(A, i) is not str_arr_is_na(B, i)): return False return is_index_equal return sdc_array_equal_str_arr_impl else: both_range_indexes = isinstance(A, RangeIndexType) and isinstance( B, RangeIndexType) def sdc_array_equal_impl(A, B): if both_range_indexes == True: # noqa if len(A) != len(B): return False if len(A) == 0: return True if len(A) == 1: return A.start == B.start return A.start == B.start and A.step == B.step else: if len(A) != len(B): return False # FIXME_Numba#5157: change to simple A == B when issue is resolved eq_res_size = len(A) eq_res = numpy.empty(eq_res_size, dtype=types.bool_) for i in numba.prange(eq_res_size): eq_res[i] = A[i] == B[i] return numpy.all(eq_res) return sdc_array_equal_impl
def pd_int64_index_equals_overload(self, other): if not isinstance(self, Int64IndexType): return None _func_name = 'Method equals().' if not isinstance(other, sdc_pandas_index_types): raise SDCLimitation( f"{_func_name} Unsupported parameter. Given 'other': {other}") if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) def pd_int64_index_equals_impl(self, other): return sdc_numeric_indexes_equals(self, other) return pd_int64_index_equals_impl
def pd_multi_index_eq_overload(self, other): _func_name = 'Operator eq.' self_is_multi_index = isinstance(self, MultiIndexType) other_is_multi_index = isinstance(other, MultiIndexType) both_are_multi_indexes = self_is_multi_index and other_is_multi_index if not (both_are_multi_indexes and check_types_comparable(self, other) or (self_is_multi_index and other is getattr(self, 'dtype', types.none)) or (self is getattr(other, 'dtype', types.none) and other_is_multi_index)): raise TypingError('{} Not allowed for non comparable types. \ Given: self={}, other={}'.format(_func_name, self, other)) def pd_multi_index_eq_impl(self, other): if both_are_multi_indexes == True: # noqa self_size = len(self) if len(self) != len(other): raise ValueError("Lengths must match to compare") if self.nlevels != other.nlevels: res = np.zeros(self_size, dtype=types.bool_) else: res = np.empty(self_size, dtype=types.bool_) for i in prange(self_size): res[i] = self[i] == other[i] elif self_is_multi_index == True: # noqa self_size = len(self) res = np.empty(self_size, dtype=types.bool_) for i in prange(self_size): res[i] = self[i] == other else: other_size = len(other) res = np.empty(other_size, dtype=types.bool_) for i in prange(other_size): res[i] = self == other[i] return list( res ) # FIXME_Numba#5157: result must be np.array, remove list when Numba is fixed return pd_multi_index_eq_impl
def pd_positional_index_append_overload(self, other): if not isinstance(self, PositionalIndexType): return None _func_name = 'Method append().' ty_checker = TypeChecker(_func_name) if not isinstance(other, sdc_pandas_index_types): ty_checker.raise_exc(other, 'pandas index', 'other') if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) def pd_positional_index_append_impl(self, other): _self = self._data return _self.append(other) return pd_positional_index_append_impl
def pd_range_index_append_overload(self, other): if not isinstance(self, RangeIndexType): return None _func_name = 'Method append().' ty_checker = TypeChecker(_func_name) if not isinstance(other, sdc_pandas_index_types): ty_checker.raise_exc(other, 'pandas index', 'other') if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) def pd_range_index_append_impl(self, other): int64_index = pd.Int64Index(self.values, name=self._name) return int64_index.append(other) return pd_range_index_append_impl
def sdc_array_equal_overload(A, B): """ Checks 1D sequences A and B of comparable dtypes are equal """ valid_arg_types = sdc_pandas_df_column_types if not (isinstance(A, valid_arg_types) or isinstance(B, valid_arg_types)): return None _func_name = "numpy-like 'array_equal'" if not check_types_comparable(A, B): msg = '{} Not comparable arguments. Given: A={}, B={}' raise TypingError(msg.format(_func_name, A, B)) if (A == string_array_type and A == B): def sdc_array_equal_str_arr_impl(A, B): if A is B: return True is_index_equal = (len(A) == len(B) and num_total_chars(A) == num_total_chars(B)) for i in numpy.arange(len(A)): if (A[i] != B[i] or str_arr_is_na(A, i) is not str_arr_is_na(B, i)): return False return is_index_equal return sdc_array_equal_str_arr_impl else: def sdc_array_equal_impl(A, B): if A is B: return True if len(A) != len(B): return False # FIXME_Numba#5157: change to simple A == B when issue is resolved eq_res_size = len(A) eq_res = numpy.empty(eq_res_size, dtype=types.bool_) for i in numba.prange(eq_res_size): eq_res[i] = A[i] == B[i] return numpy.all(eq_res) return sdc_array_equal_impl
def pd_range_index_eq_overload(self, other): _func_name = 'Operator eq.' if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) self_is_range_index = isinstance(self, RangeIndexType) other_is_range_index = isinstance(other, RangeIndexType) possible_arg_types = (types.Array, types.Number) + sdc_pandas_index_types if not (self_is_range_index and other_is_range_index or (self_is_range_index and isinstance(other, possible_arg_types)) or (isinstance(self, possible_arg_types) and other_is_range_index)): return None def pd_range_index_eq_impl(self, other): return sdc_indexes_operator_eq(self, other) return pd_range_index_eq_impl
def pd_multi_index_ne_overload(self, other): _func_name = 'Operator ne.' self_is_multi_index = isinstance(self, MultiIndexType) other_is_multi_index = isinstance(other, MultiIndexType) both_are_multi_indexes = self_is_multi_index and other_is_multi_index if not (both_are_multi_indexes and check_types_comparable(self, other) or (self_is_multi_index and other is getattr(self, 'dtype', types.none)) or (self is getattr(other, 'dtype', types.none) and other_is_multi_index)): raise TypingError('{} Not allowed for non comparable types. \ Given: self={}, other={}'.format(_func_name, self, other)) def pd_multi_index_ne_impl(self, other): eq_res = np.asarray( self == other) # FIXME_Numba#5157: remove np.asarray and return as list return list(~eq_res) return pd_multi_index_ne_impl
def pd_multi_index_append_overload(self, other): if not isinstance(self, MultiIndexType): return None _func_name = 'Method append().' ty_checker = TypeChecker(_func_name) if not (isinstance(other, MultiIndexType)): ty_checker.raise_exc(other, 'pandas MultiIndex', 'other') if not check_types_comparable(self, other): raise TypingError('{} Not allowed for non comparable indexes. \ Given: self={}, other={}'.format(_func_name, self, other)) def pd_multi_index_append_impl(self, other): self_and_other_data = _multi_index_binop_helper(self, other) tup_append_level_res = sdc_tuple_map( lambda x: _multi_index_append_level(*x), self_and_other_data) new_levels, new_codes = sdc_tuple_unzip(tup_append_level_res) return pd.MultiIndex(levels=new_levels, codes=new_codes) return pd_multi_index_append_impl
def sdc_pandas_series_operator_binop(self, other): """ Pandas Series operator :attr:`pandas.Series.binop` implementation Note: Currently implemented for numeric Series only. Differs from Pandas in returning Series with fixed dtype :obj:`float64` .. only:: developer **Test**: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op1* python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op2* python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_operator_binop* Parameters ---------- series: :obj:`pandas.Series` Input series other: :obj:`pandas.Series` or :obj:`scalar` Series or scalar value to be used as a second argument of binary operation Returns ------- :obj:`pandas.Series` The result of the operation """ _func_name = 'Operator binop().' ty_checker = TypeChecker('Operator binop().') self_is_series, other_is_series = isinstance(self, SeriesType), isinstance( other, SeriesType) if not (self_is_series or other_is_series): return None # this overload is not for string series self_is_string_series = self_is_series and isinstance( self.dtype, types.UnicodeType) other_is_string_series = other_is_series and isinstance( other.dtype, types.UnicodeType) if self_is_string_series or other_is_string_series: return None if not isinstance(self, (SeriesType, types.Number)): ty_checker.raise_exc(self, 'pandas.series or scalar', 'self') if not isinstance(other, (SeriesType, types.Number)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: none_or_numeric_indexes = ((isinstance(self.index, types.NoneType) or check_index_is_numeric(self)) and (isinstance(other.index, types.NoneType) or check_index_is_numeric(other))) series_indexes_comparable = check_types_comparable( self.index, other.index) or none_or_numeric_indexes if not series_indexes_comparable: raise TypingError( '{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format( _func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) # specializations for numeric series only if not operands_are_series: def _series_operator_binop_scalar_impl(self, other): if self_is_series == True: # noqa result_data = numpy.empty(len(self._data), dtype=numpy.float64) result_data[:] = self._data + numpy.float64(other) return pandas.Series(result_data, index=self._index, name=self._name) else: result_data = numpy.empty(len(other._data), dtype=numpy.float64) result_data[:] = numpy.float64(self) + other._data return pandas.Series(result_data, index=other._index, name=other._name) return _series_operator_binop_scalar_impl else: # both operands are numeric series # optimization for series with default indexes, that can be aligned differently if (isinstance(self.index, types.NoneType) and isinstance(other.index, types.NoneType)): def _series_operator_binop_none_indexes_impl(self, other): if (len(self._data) == len(other._data)): result_data = astype(self._data, numpy.float64) result_data = result_data + other._data return pandas.Series(result_data) else: left_size, right_size = len(self._data), len(other._data) min_data_size = min(left_size, right_size) max_data_size = max(left_size, right_size) result_data = numpy.empty(max_data_size, dtype=numpy.float64) if (left_size == min_data_size): result_data[:min_data_size] = self._data result_data[min_data_size:] = numpy.nan result_data = result_data + other._data else: result_data[:min_data_size] = other._data result_data[min_data_size:] = numpy.nan result_data = self._data + result_data return pandas.Series(result_data) return _series_operator_binop_none_indexes_impl else: # for numeric indexes find common dtype to be used when creating joined index if none_or_numeric_indexes: ty_left_index_dtype = types.int64 if isinstance( self.index, types.NoneType) else self.index.dtype ty_right_index_dtype = types.int64 if isinstance( other.index, types.NoneType) else other.index.dtype numba_index_common_dtype = find_common_dtype_from_numpy_dtypes( [ty_left_index_dtype, ty_right_index_dtype], []) def _series_operator_binop_common_impl(self, other): left_index, right_index = self.index, other.index # check if indexes are equal and series don't have to be aligned if sdc_check_indexes_equal(left_index, right_index): result_data = numpy.empty(len(self._data), dtype=numpy.float64) result_data[:] = self._data + other._data if none_or_numeric_indexes == True: # noqa result_index = astype(left_index, numba_index_common_dtype) else: result_index = self._index return pandas.Series(result_data, index=result_index) # TODO: replace below with core join(how='outer', return_indexers=True) when implemented joined_index, left_indexer, right_indexer = sdc_join_series_indexes( left_index, right_index) result_size = len(joined_index) left_values = numpy.empty(result_size, dtype=numpy.float64) right_values = numpy.empty(result_size, dtype=numpy.float64) for i in numba.prange(result_size): left_pos, right_pos = left_indexer[i], right_indexer[i] left_values[i] = self._data[ left_pos] if left_pos != -1 else numpy.nan right_values[i] = other._data[ right_pos] if right_pos != -1 else numpy.nan result_data = left_values + right_values return pandas.Series(result_data, joined_index) return _series_operator_binop_common_impl return None
def sdc_pandas_series_operator_comp_binop(self, other): """ Pandas Series operator :attr:`pandas.Series.comp_binop` implementation .. only:: developer **Test**: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op7* python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_operator_comp_binop* Parameters ---------- series: :obj:`pandas.Series` Input series other: :obj:`pandas.Series` or :obj:`scalar` Series or scalar value to be used as a second argument of binary operation Returns ------- :obj:`pandas.Series` The result of the operation """ _func_name = 'Operator comp_binop().' ty_checker = TypeChecker('Operator comp_binop().') self_is_series, other_is_series = isinstance(self, SeriesType), isinstance( other, SeriesType) if not (self_is_series or other_is_series): return None if not isinstance(self, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(self, 'pandas.series or scalar', 'self') if not isinstance(other, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: none_or_numeric_indexes = ((isinstance(self.index, types.NoneType) or check_index_is_numeric(self)) and (isinstance(other.index, types.NoneType) or check_index_is_numeric(other))) series_indexes_comparable = check_types_comparable( self.index, other.index) or none_or_numeric_indexes if not series_indexes_comparable: raise TypingError( '{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format( _func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) if not operands_are_series: def _series_operator_comp_binop_scalar_impl(self, other): if self_is_series == True: # noqa return pandas.Series(self._data < other, index=self._index, name=self._name) else: return pandas.Series(self < other._data, index=other._index, name=other._name) return _series_operator_comp_binop_scalar_impl else: # optimization for series with default indexes, that can be aligned differently if (isinstance(self.index, types.NoneType) and isinstance(other.index, types.NoneType)): def _series_operator_comp_binop_none_indexes_impl(self, other): left_size, right_size = len(self._data), len(other._data) if (left_size == right_size): return pandas.Series(self._data < other._data) else: raise ValueError( "Can only compare identically-labeled Series objects") return _series_operator_comp_binop_none_indexes_impl else: if none_or_numeric_indexes: ty_left_index_dtype = types.int64 if isinstance( self.index, types.NoneType) else self.index.dtype ty_right_index_dtype = types.int64 if isinstance( other.index, types.NoneType) else other.index.dtype numba_index_common_dtype = find_common_dtype_from_numpy_dtypes( [ty_left_index_dtype, ty_right_index_dtype], []) def _series_operator_comp_binop_common_impl(self, other): left_index, right_index = self.index, other.index if sdc_check_indexes_equal(left_index, right_index): if none_or_numeric_indexes == True: # noqa new_index = astype(left_index, numba_index_common_dtype) else: new_index = self._index return pandas.Series(self._data < other._data, new_index) else: raise ValueError( "Can only compare identically-labeled Series objects") return _series_operator_comp_binop_common_impl return None
def sdc_pandas_series_comp_binop(self, other, level=None, fill_value=None, axis=0): """ Intel Scalable Dataframe Compiler User Guide ******************************************** Pandas API: pandas.Series.comp_binop Limitations ----------- Parameters ``level`` and ``axis`` are currently unsupported by Intel Scalable Dataframe Compiler Examples -------- .. literalinclude:: ../../../examples/series/series_comp_binop.py :language: python :lines: 27- :caption: :name: ex_series_comp_binop .. command-output:: python ./series/series_comp_binop.py :cwd: ../../../examples Intel Scalable Dataframe Compiler Developer Guide ************************************************* Pandas Series method :meth:`pandas.Series.comp_binop` implementation. .. only:: developer Test: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op8 """ _func_name = 'Method comp_binop().' ty_checker = TypeChecker(_func_name) ty_checker.check(self, SeriesType) if not (isinstance(level, types.Omitted) or level is None): ty_checker.raise_exc(level, 'None', 'level') if not (isinstance(fill_value, (types.Omitted, types.Number, types.UnicodeType, types.NoneType)) or fill_value is None): ty_checker.raise_exc(fill_value, 'scalar', 'fill_value') if not (isinstance(axis, types.Omitted) or axis == 0): ty_checker.raise_exc(axis, 'int', 'axis') self_is_series, other_is_series = isinstance(self, SeriesType), isinstance(other, SeriesType) if not (self_is_series or other_is_series): return None if not isinstance(self, SeriesType): ty_checker.raise_exc(self, 'pandas.series', 'self') if not isinstance(other, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: series_indexes_comparable = check_types_comparable(self.index, other.index) if not series_indexes_comparable: raise TypingError('{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format(_func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) # specializations for both numeric and string series def series_comp_binop_wrapper(self, other, level=None, fill_value=None, axis=0): return sdc_comp_binop(self, other, fill_value) return series_comp_binop_wrapper
def sdc_pandas_series_binop(self, other, level=None, fill_value=None, axis=0): """ Intel Scalable Dataframe Compiler User Guide ******************************************** Pandas API: pandas.Series.binop Limitations ----------- Parameters ``level`` and ``axis`` are currently unsupported by Intel Scalable Dataframe Compiler Examples -------- .. literalinclude:: ../../../examples/series/series_binop.py :language: python :lines: 27- :caption: :name: ex_series_binop .. command-output:: python ./series/series_binop.py :cwd: ../../../examples Intel Scalable Dataframe Compiler Developer Guide ************************************************* Pandas Series method :meth:`pandas.Series.binop` implementation. .. only:: developer Test: python -m sdc.runtests sdc.tests.test_series.TestSeries.test_series_op5 """ _func_name = 'Method binop().' ty_checker = TypeChecker(_func_name) self_is_series, other_is_series = isinstance(self, SeriesType), isinstance( other, SeriesType) if not (self_is_series or other_is_series): return None # this overload is not for string series self_is_string_series = self_is_series and isinstance( self.dtype, types.UnicodeType) other_is_string_series = other_is_series and isinstance( other.dtype, types.UnicodeType) if self_is_string_series or other_is_string_series: return None if not isinstance(self, (SeriesType, types.Number)): ty_checker.raise_exc(self, 'pandas.series or scalar', 'self') if not isinstance(other, (SeriesType, types.Number)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: none_or_numeric_indexes = ((isinstance(self.index, types.NoneType) or check_index_is_numeric(self)) and (isinstance(other.index, types.NoneType) or check_index_is_numeric(other))) series_indexes_comparable = check_types_comparable( self.index, other.index) or none_or_numeric_indexes if not series_indexes_comparable: raise TypingError( '{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format( _func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) if not isinstance(level, types.Omitted) and level is not None: ty_checker.raise_exc(level, 'None', 'level') if not isinstance(fill_value, (types.Omitted, types.Number, types.NoneType)) and fill_value is not None: ty_checker.raise_exc(fill_value, 'number', 'fill_value') fill_value_is_none = isinstance( fill_value, (types.NoneType, types.Omitted)) or fill_value is None if not isinstance(axis, types.Omitted) and axis != 0: ty_checker.raise_exc(axis, 'int', 'axis') # specializations for numeric series only if not operands_are_series: def _series_binop_scalar_impl(self, other, level=None, fill_value=None, axis=0): if self_is_series == True: # noqa numpy_like.fillna(self._data, inplace=True, value=fill_value) result_data = numpy.empty(len(self._data), dtype=numpy.float64) result_data[:] = self._data + numpy.float64(other) return pandas.Series(result_data, index=self._index, name=self._name) else: numpy_like.fillna(other._data, inplace=True, value=fill_value) result_data = numpy.empty(len(other._data), dtype=numpy.float64) result_data[:] = numpy.float64(self) + other._data return pandas.Series(result_data, index=other._index, name=other._name) return _series_binop_scalar_impl else: # both operands are numeric series # optimization for series with default indexes, that can be aligned differently if (isinstance(self.index, types.NoneType) and isinstance(other.index, types.NoneType)): def _series_binop_none_indexes_impl(self, other, level=None, fill_value=None, axis=0): numpy_like.fillna(self._data, inplace=True, value=fill_value) numpy_like.fillna(other._data, inplace=True, value=fill_value) if (len(self._data) == len(other._data)): result_data = numpy_like.astype(self._data, numpy.float64) result_data = result_data + other._data return pandas.Series(result_data) else: left_size, right_size = len(self._data), len(other._data) min_data_size = min(left_size, right_size) max_data_size = max(left_size, right_size) result_data = numpy.empty(max_data_size, dtype=numpy.float64) _fill_value = numpy.nan if fill_value_is_none == True else fill_value # noqa if (left_size == min_data_size): result_data[:min_data_size] = self._data for i in range(min_data_size, len(result_data)): result_data[i] = _fill_value result_data = result_data + other._data else: result_data[:min_data_size] = other._data for i in range(min_data_size, len(result_data)): result_data[i] = _fill_value result_data = self._data + result_data return pandas.Series(result_data) return _series_binop_none_indexes_impl else: left_index_is_range = isinstance(self.index, (RangeIndexType, types.NoneType)) right_index_is_range = isinstance(other.index, (RangeIndexType, types.NoneType)) check_index_equal = left_index_is_range and right_index_is_range self_index_dtype = RangeIndexType.dtype if isinstance( self.index, types.NoneType) else self.index.dtype other_index_dtype = RangeIndexType.dtype if isinstance( other.index, types.NoneType) else other.index.dtype index_dtypes_match = self_index_dtype == other_index_dtype if not index_dtypes_match: numba_index_common_dtype = find_common_dtype_from_numpy_dtypes( [self_index_dtype, other_index_dtype], []) else: numba_index_common_dtype = self_index_dtype def _series_binop_common_impl(self, other, level=None, fill_value=None, axis=0): left_index, right_index = self.index, other.index numpy_like.fillna(self._data, inplace=True, value=fill_value) numpy_like.fillna(other._data, inplace=True, value=fill_value) if check_index_equal == True: # noqa equal_indexes = numpy_like.array_equal( left_index, right_index) else: equal_indexes = False if (left_index is right_index or equal_indexes): result_data = numpy.empty(len(self._data), dtype=numpy.float64) result_data[:] = self._data + other._data if index_dtypes_match == False: # noqa result_index = numpy_like.astype( left_index, numba_index_common_dtype) else: result_index = left_index.values if left_index_is_range == True else left_index # noqa return pandas.Series(result_data, index=result_index) # TODO: replace below with core join(how='outer', return_indexers=True) when implemented joined_index, left_indexer, right_indexer = sdc_join_series_indexes( left_index, right_index) result_size = len(joined_index) left_values = numpy.empty(result_size, dtype=numpy.float64) right_values = numpy.empty(result_size, dtype=numpy.float64) _fill_value = numpy.nan if fill_value_is_none == True else fill_value # noqa for i in range(result_size): left_pos, right_pos = left_indexer[i], right_indexer[i] left_values[i] = self._data[ left_pos] if left_pos != -1 else _fill_value right_values[i] = other._data[ right_pos] if right_pos != -1 else _fill_value result_data = left_values + right_values return pandas.Series(result_data, joined_index) return _series_binop_common_impl return None
def sdc_pandas_series_comp_binop(self, other, level=None, fill_value=None, axis=0): """ Intel Scalable Dataframe Compiler User Guide ******************************************** Pandas API: pandas.Series.comp_binop Limitations ----------- Parameters ``level`` and ``axis`` are currently unsupported by Intel Scalable Dataframe Compiler Examples -------- .. literalinclude:: ../../../examples/series/series_comp_binop.py :language: python :lines: 27- :caption: :name: ex_series_comp_binop .. command-output:: python ./series/series_comp_binop.py :cwd: ../../../examples Intel Scalable Dataframe Compiler Developer Guide ************************************************* Pandas Series method :meth:`pandas.Series.comp_binop` implementation. .. only:: developer Test: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op8 """ _func_name = 'Method comp_binop().' ty_checker = TypeChecker(_func_name) ty_checker.check(self, SeriesType) if not (isinstance(level, types.Omitted) or level is None): ty_checker.raise_exc(level, 'None', 'level') if not isinstance(fill_value, (types.Omitted, types.Number, types.NoneType)) and fill_value is not None: ty_checker.raise_exc(fill_value, 'number', 'fill_value') if not (isinstance(axis, types.Omitted) or axis == 0): ty_checker.raise_exc(axis, 'int', 'axis') self_is_series, other_is_series = isinstance(self, SeriesType), isinstance( other, SeriesType) if not (self_is_series or other_is_series): return None if not isinstance(self, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(self, 'pandas.series or scalar', 'self') if not isinstance(other, (SeriesType, types.Number, types.UnicodeType)): ty_checker.raise_exc(other, 'pandas.series or scalar', 'other') operands_are_series = self_is_series and other_is_series if operands_are_series: none_or_numeric_indexes = ((isinstance(self.index, types.NoneType) or check_index_is_numeric(self)) and (isinstance(other.index, types.NoneType) or check_index_is_numeric(other))) series_indexes_comparable = check_types_comparable( self.index, other.index) or none_or_numeric_indexes if not series_indexes_comparable: raise TypingError( '{} Not implemented for series with not-comparable indexes. \ Given: self.index={}, other.index={}'.format( _func_name, self.index, other.index)) series_data_comparable = check_types_comparable(self, other) if not series_data_comparable: raise TypingError('{} Not supported for not-comparable operands. \ Given: self={}, other={}'.format(_func_name, self, other)) fill_value_is_none = isinstance( fill_value, (types.NoneType, types.Omitted)) or fill_value is None if not operands_are_series: def _series_comp_binop_scalar_impl(self, other, level=None, fill_value=None, axis=0): if self_is_series == True: # noqa numpy_like.fillna(self._data, inplace=True, value=fill_value) return pandas.Series(self._data < other, index=self._index, name=self._name) else: numpy_like.fillna(other._data, inplace=True, value=fill_value) return pandas.Series(self < other._data, index=other._index, name=other._name) return _series_comp_binop_scalar_impl else: # optimization for series with default indexes, that can be aligned differently if (isinstance(self.index, types.NoneType) and isinstance(other.index, types.NoneType)): def _series_comp_binop_none_indexes_impl(self, other, level=None, fill_value=None, axis=0): numpy_like.fillna(self._data, inplace=True, value=fill_value) numpy_like.fillna(other._data, inplace=True, value=fill_value) left_size, right_size = len(self._data), len(other._data) if (left_size == right_size): return pandas.Series(self._data < other._data) else: raise ValueError( "Can only compare identically-labeled Series objects") return _series_comp_binop_none_indexes_impl else: left_index_is_range = isinstance(self.index, (RangeIndexType, types.NoneType)) index_dtypes_match = self.index.dtype == other.index.dtype if not index_dtypes_match: numba_index_common_dtype = find_common_dtype_from_numpy_dtypes( [self.index.dtype, other.index.dtype], []) else: numba_index_common_dtype = self.index.dtype def _series_comp_binop_common_impl(self, other, level=None, fill_value=None, axis=0): numpy_like.fillna(self._data, inplace=True, value=fill_value) numpy_like.fillna(other._data, inplace=True, value=fill_value) left_index, right_index = self.index, other.index if (left_index is right_index or numpy_like.array_equal(left_index, right_index)): if index_dtypes_match == False: # noqa new_index = numpy_like.astype( left_index, numba_index_common_dtype) else: new_index = left_index.values if left_index_is_range == True else left_index # noqa return pandas.Series(self._data < other._data, new_index) else: raise ValueError( "Can only compare identically-labeled Series objects") return _series_comp_binop_common_impl return None