12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076 |
- # -*- coding: utf-8 -*-
- # Arithmetc tests for DataFrame/Series/Index/Array classes that should
- # behave identically.
- # Specifically for numeric dtypes
- from decimal import Decimal
- from itertools import combinations
- import operator
- import numpy as np
- import pytest
- from pandas.compat import PY3, Iterable
- import pandas as pd
- from pandas import Index, Series, Timedelta, TimedeltaIndex
- from pandas.core import ops
- import pandas.util.testing as tm
- # ------------------------------------------------------------------
- # Comparisons
- class TestNumericComparisons(object):
- def test_operator_series_comparison_zerorank(self):
- # GH#13006
- result = np.float64(0) > pd.Series([1, 2, 3])
- expected = 0.0 > pd.Series([1, 2, 3])
- tm.assert_series_equal(result, expected)
- result = pd.Series([1, 2, 3]) < np.float64(0)
- expected = pd.Series([1, 2, 3]) < 0.0
- tm.assert_series_equal(result, expected)
- result = np.array([0, 1, 2])[0] > pd.Series([0, 1, 2])
- expected = 0.0 > pd.Series([1, 2, 3])
- tm.assert_series_equal(result, expected)
- def test_df_numeric_cmp_dt64_raises(self):
- # GH#8932, GH#22163
- ts = pd.Timestamp.now()
- df = pd.DataFrame({'x': range(5)})
- with pytest.raises(TypeError):
- df > ts
- with pytest.raises(TypeError):
- df < ts
- with pytest.raises(TypeError):
- ts < df
- with pytest.raises(TypeError):
- ts > df
- assert not (df == ts).any().any()
- assert (df != ts).all().all()
- def test_compare_invalid(self):
- # GH#8058
- # ops testing
- a = pd.Series(np.random.randn(5), name=0)
- b = pd.Series(np.random.randn(5))
- b.name = pd.Timestamp('2000-01-01')
- tm.assert_series_equal(a / b, 1 / (b / a))
- # ------------------------------------------------------------------
- # Numeric dtypes Arithmetic with Timedelta Scalar
- class TestNumericArraylikeArithmeticWithTimedeltaLike(object):
- # TODO: also check name retentention
- @pytest.mark.parametrize('box_cls', [np.array, pd.Index, pd.Series])
- @pytest.mark.parametrize('left', [
- pd.RangeIndex(10, 40, 10)] + [cls([10, 20, 30], dtype=dtype)
- for dtype in ['i1', 'i2', 'i4', 'i8',
- 'u1', 'u2', 'u4', 'u8',
- 'f2', 'f4', 'f8']
- for cls in [pd.Series, pd.Index]],
- ids=lambda x: type(x).__name__ + str(x.dtype))
- def test_mul_td64arr(self, left, box_cls):
- # GH#22390
- right = np.array([1, 2, 3], dtype='m8[s]')
- right = box_cls(right)
- expected = pd.TimedeltaIndex(['10s', '40s', '90s'])
- if isinstance(left, pd.Series) or box_cls is pd.Series:
- expected = pd.Series(expected)
- result = left * right
- tm.assert_equal(result, expected)
- result = right * left
- tm.assert_equal(result, expected)
- # TODO: also check name retentention
- @pytest.mark.parametrize('box_cls', [np.array, pd.Index, pd.Series])
- @pytest.mark.parametrize('left', [
- pd.RangeIndex(10, 40, 10)] + [cls([10, 20, 30], dtype=dtype)
- for dtype in ['i1', 'i2', 'i4', 'i8',
- 'u1', 'u2', 'u4', 'u8',
- 'f2', 'f4', 'f8']
- for cls in [pd.Series, pd.Index]],
- ids=lambda x: type(x).__name__ + str(x.dtype))
- def test_div_td64arr(self, left, box_cls):
- # GH#22390
- right = np.array([10, 40, 90], dtype='m8[s]')
- right = box_cls(right)
- expected = pd.TimedeltaIndex(['1s', '2s', '3s'])
- if isinstance(left, pd.Series) or box_cls is pd.Series:
- expected = pd.Series(expected)
- result = right / left
- tm.assert_equal(result, expected)
- result = right // left
- tm.assert_equal(result, expected)
- with pytest.raises(TypeError):
- left / right
- with pytest.raises(TypeError):
- left // right
- # TODO: de-duplicate with test_numeric_arr_mul_tdscalar
- def test_ops_series(self):
- # regression test for G#H8813
- td = Timedelta('1 day')
- other = pd.Series([1, 2])
- expected = pd.Series(pd.to_timedelta(['1 day', '2 days']))
- tm.assert_series_equal(expected, td * other)
- tm.assert_series_equal(expected, other * td)
- # TODO: also test non-nanosecond timedelta64 and Tick objects;
- # see test_numeric_arr_rdiv_tdscalar for note on these failing
- @pytest.mark.parametrize('scalar_td', [
- Timedelta(days=1),
- Timedelta(days=1).to_timedelta64(),
- Timedelta(days=1).to_pytimedelta()],
- ids=lambda x: type(x).__name__)
- def test_numeric_arr_mul_tdscalar(self, scalar_td, numeric_idx, box):
- # GH#19333
- index = numeric_idx
- expected = pd.timedelta_range('0 days', '4 days')
- index = tm.box_expected(index, box)
- expected = tm.box_expected(expected, box)
- result = index * scalar_td
- tm.assert_equal(result, expected)
- commute = scalar_td * index
- tm.assert_equal(commute, expected)
- def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
- index = numeric_idx[1:3]
- expected = TimedeltaIndex(['3 Days', '36 Hours'])
- index = tm.box_expected(index, box)
- expected = tm.box_expected(expected, box)
- result = three_days / index
- tm.assert_equal(result, expected)
- with pytest.raises(TypeError):
- index / three_days
- @pytest.mark.parametrize('other', [
- pd.Timedelta(hours=31),
- pd.Timedelta(hours=31).to_pytimedelta(),
- pd.Timedelta(hours=31).to_timedelta64(),
- pd.Timedelta(hours=31).to_timedelta64().astype('m8[h]'),
- np.timedelta64('NaT'),
- np.timedelta64('NaT', 'D'),
- pd.offsets.Minute(3),
- pd.offsets.Second(0)])
- def test_add_sub_timedeltalike_invalid(self, numeric_idx, other, box):
- left = tm.box_expected(numeric_idx, box)
- with pytest.raises(TypeError):
- left + other
- with pytest.raises(TypeError):
- other + left
- with pytest.raises(TypeError):
- left - other
- with pytest.raises(TypeError):
- other - left
- # ------------------------------------------------------------------
- # Arithmetic
- class TestDivisionByZero(object):
- def test_div_zero(self, zero, numeric_idx):
- idx = numeric_idx
- expected = pd.Index([np.nan, np.inf, np.inf, np.inf, np.inf],
- dtype=np.float64)
- result = idx / zero
- tm.assert_index_equal(result, expected)
- ser_compat = Series(idx).astype('i8') / np.array(zero).astype('i8')
- tm.assert_series_equal(ser_compat, Series(result))
- def test_floordiv_zero(self, zero, numeric_idx):
- idx = numeric_idx
- expected = pd.Index([np.nan, np.inf, np.inf, np.inf, np.inf],
- dtype=np.float64)
- result = idx // zero
- tm.assert_index_equal(result, expected)
- ser_compat = Series(idx).astype('i8') // np.array(zero).astype('i8')
- tm.assert_series_equal(ser_compat, Series(result))
- def test_mod_zero(self, zero, numeric_idx):
- idx = numeric_idx
- expected = pd.Index([np.nan, np.nan, np.nan, np.nan, np.nan],
- dtype=np.float64)
- result = idx % zero
- tm.assert_index_equal(result, expected)
- ser_compat = Series(idx).astype('i8') % np.array(zero).astype('i8')
- tm.assert_series_equal(ser_compat, Series(result))
- def test_divmod_zero(self, zero, numeric_idx):
- idx = numeric_idx
- exleft = pd.Index([np.nan, np.inf, np.inf, np.inf, np.inf],
- dtype=np.float64)
- exright = pd.Index([np.nan, np.nan, np.nan, np.nan, np.nan],
- dtype=np.float64)
- result = divmod(idx, zero)
- tm.assert_index_equal(result[0], exleft)
- tm.assert_index_equal(result[1], exright)
- # ------------------------------------------------------------------
- @pytest.mark.parametrize('dtype2', [
- np.int64, np.int32, np.int16, np.int8,
- np.float64, np.float32, np.float16,
- np.uint64, np.uint32, np.uint16, np.uint8])
- @pytest.mark.parametrize('dtype1', [np.int64, np.float64, np.uint64])
- def test_ser_div_ser(self, dtype1, dtype2):
- # no longer do integer div for any ops, but deal with the 0's
- first = Series([3, 4, 5, 8], name='first').astype(dtype1)
- second = Series([0, 0, 0, 3], name='second').astype(dtype2)
- with np.errstate(all='ignore'):
- expected = Series(first.values.astype(np.float64) / second.values,
- dtype='float64', name=None)
- expected.iloc[0:3] = np.inf
- result = first / second
- tm.assert_series_equal(result, expected)
- assert not result.equals(second / first)
- def test_rdiv_zero_compat(self):
- # GH#8674
- zero_array = np.array([0] * 5)
- data = np.random.randn(5)
- expected = Series([0.] * 5)
- result = zero_array / Series(data)
- tm.assert_series_equal(result, expected)
- result = Series(zero_array) / data
- tm.assert_series_equal(result, expected)
- result = Series(zero_array) / Series(data)
- tm.assert_series_equal(result, expected)
- def test_div_zero_inf_signs(self):
- # GH#9144, inf signing
- ser = Series([-1, 0, 1], name='first')
- expected = Series([-np.inf, np.nan, np.inf], name='first')
- result = ser / 0
- tm.assert_series_equal(result, expected)
- def test_rdiv_zero(self):
- # GH#9144
- ser = Series([-1, 0, 1], name='first')
- expected = Series([0.0, np.nan, 0.0], name='first')
- result = 0 / ser
- tm.assert_series_equal(result, expected)
- def test_floordiv_div(self):
- # GH#9144
- ser = Series([-1, 0, 1], name='first')
- result = ser // 0
- expected = Series([-np.inf, np.nan, np.inf], name='first')
- tm.assert_series_equal(result, expected)
- def test_df_div_zero_df(self):
- # integer div, but deal with the 0's (GH#9144)
- df = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- result = df / df
- first = pd.Series([1.0, 1.0, 1.0, 1.0])
- second = pd.Series([np.nan, np.nan, np.nan, 1])
- expected = pd.DataFrame({'first': first, 'second': second})
- tm.assert_frame_equal(result, expected)
- def test_df_div_zero_array(self):
- # integer div, but deal with the 0's (GH#9144)
- df = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- first = pd.Series([1.0, 1.0, 1.0, 1.0])
- second = pd.Series([np.nan, np.nan, np.nan, 1])
- expected = pd.DataFrame({'first': first, 'second': second})
- with np.errstate(all='ignore'):
- arr = df.values.astype('float') / df.values
- result = pd.DataFrame(arr, index=df.index,
- columns=df.columns)
- tm.assert_frame_equal(result, expected)
- def test_df_div_zero_int(self):
- # integer div, but deal with the 0's (GH#9144)
- df = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- result = df / 0
- expected = pd.DataFrame(np.inf, index=df.index, columns=df.columns)
- expected.iloc[0:3, 1] = np.nan
- tm.assert_frame_equal(result, expected)
- # numpy has a slightly different (wrong) treatment
- with np.errstate(all='ignore'):
- arr = df.values.astype('float64') / 0
- result2 = pd.DataFrame(arr, index=df.index,
- columns=df.columns)
- tm.assert_frame_equal(result2, expected)
- def test_df_div_zero_series_does_not_commute(self):
- # integer div, but deal with the 0's (GH#9144)
- df = pd.DataFrame(np.random.randn(10, 5))
- ser = df[0]
- res = ser / df
- res2 = df / ser
- assert not res.fillna(0).equals(res2.fillna(0))
- # ------------------------------------------------------------------
- # Mod By Zero
- def test_df_mod_zero_df(self):
- # GH#3590, modulo as ints
- df = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- # this is technically wrong, as the integer portion is coerced to float
- # ###
- first = pd.Series([0, 0, 0, 0], dtype='float64')
- second = pd.Series([np.nan, np.nan, np.nan, 0])
- expected = pd.DataFrame({'first': first, 'second': second})
- result = df % df
- tm.assert_frame_equal(result, expected)
- def test_df_mod_zero_array(self):
- # GH#3590, modulo as ints
- df = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- # this is technically wrong, as the integer portion is coerced to float
- # ###
- first = pd.Series([0, 0, 0, 0], dtype='float64')
- second = pd.Series([np.nan, np.nan, np.nan, 0])
- expected = pd.DataFrame({'first': first, 'second': second})
- # numpy has a slightly different (wrong) treatment
- with np.errstate(all='ignore'):
- arr = df.values % df.values
- result2 = pd.DataFrame(arr, index=df.index,
- columns=df.columns, dtype='float64')
- result2.iloc[0:3, 1] = np.nan
- tm.assert_frame_equal(result2, expected)
- def test_df_mod_zero_int(self):
- # GH#3590, modulo as ints
- df = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- result = df % 0
- expected = pd.DataFrame(np.nan, index=df.index, columns=df.columns)
- tm.assert_frame_equal(result, expected)
- # numpy has a slightly different (wrong) treatment
- with np.errstate(all='ignore'):
- arr = df.values.astype('float64') % 0
- result2 = pd.DataFrame(arr, index=df.index, columns=df.columns)
- tm.assert_frame_equal(result2, expected)
- def test_df_mod_zero_series_does_not_commute(self):
- # GH#3590, modulo as ints
- # not commutative with series
- df = pd.DataFrame(np.random.randn(10, 5))
- ser = df[0]
- res = ser % df
- res2 = df % ser
- assert not res.fillna(0).equals(res2.fillna(0))
- class TestMultiplicationDivision(object):
- # __mul__, __rmul__, __div__, __rdiv__, __floordiv__, __rfloordiv__
- # for non-timestamp/timedelta/period dtypes
- @pytest.mark.parametrize('box', [
- pytest.param(pd.Index,
- marks=pytest.mark.xfail(reason="Index.__div__ always "
- "raises",
- raises=TypeError)),
- pd.Series,
- pd.DataFrame
- ], ids=lambda x: x.__name__)
- def test_divide_decimal(self, box):
- # resolves issue GH#9787
- ser = Series([Decimal(10)])
- expected = Series([Decimal(5)])
- ser = tm.box_expected(ser, box)
- expected = tm.box_expected(expected, box)
- result = ser / Decimal(2)
- tm.assert_equal(result, expected)
- result = ser // Decimal(2)
- tm.assert_equal(result, expected)
- def test_div_equiv_binop(self):
- # Test Series.div as well as Series.__div__
- # float/integer issue
- # GH#7785
- first = Series([1, 0], name='first')
- second = Series([-0.01, -0.02], name='second')
- expected = Series([-0.01, -np.inf])
- result = second.div(first)
- tm.assert_series_equal(result, expected, check_names=False)
- result = second / first
- tm.assert_series_equal(result, expected)
- def test_div_int(self, numeric_idx):
- # truediv under PY3
- idx = numeric_idx
- result = idx / 1
- expected = idx
- if PY3:
- expected = expected.astype('float64')
- tm.assert_index_equal(result, expected)
- result = idx / 2
- if PY3:
- expected = expected.astype('float64')
- expected = Index(idx.values / 2)
- tm.assert_index_equal(result, expected)
- @pytest.mark.parametrize('op', [operator.mul, ops.rmul, operator.floordiv])
- def test_mul_int_identity(self, op, numeric_idx, box):
- idx = numeric_idx
- idx = tm.box_expected(idx, box)
- result = op(idx, 1)
- tm.assert_equal(result, idx)
- def test_mul_int_array(self, numeric_idx):
- idx = numeric_idx
- didx = idx * idx
- result = idx * np.array(5, dtype='int64')
- tm.assert_index_equal(result, idx * 5)
- arr_dtype = 'uint64' if isinstance(idx, pd.UInt64Index) else 'int64'
- result = idx * np.arange(5, dtype=arr_dtype)
- tm.assert_index_equal(result, didx)
- def test_mul_int_series(self, numeric_idx):
- idx = numeric_idx
- didx = idx * idx
- arr_dtype = 'uint64' if isinstance(idx, pd.UInt64Index) else 'int64'
- result = idx * Series(np.arange(5, dtype=arr_dtype))
- tm.assert_series_equal(result, Series(didx))
- def test_mul_float_series(self, numeric_idx):
- idx = numeric_idx
- rng5 = np.arange(5, dtype='float64')
- result = idx * Series(rng5 + 0.1)
- expected = Series(rng5 * (rng5 + 0.1))
- tm.assert_series_equal(result, expected)
- def test_mul_index(self, numeric_idx):
- # in general not true for RangeIndex
- idx = numeric_idx
- if not isinstance(idx, pd.RangeIndex):
- result = idx * idx
- tm.assert_index_equal(result, idx ** 2)
- def test_mul_datelike_raises(self, numeric_idx):
- idx = numeric_idx
- with pytest.raises(TypeError):
- idx * pd.date_range('20130101', periods=5)
- def test_mul_size_mismatch_raises(self, numeric_idx):
- idx = numeric_idx
- with pytest.raises(ValueError):
- idx * idx[0:3]
- with pytest.raises(ValueError):
- idx * np.array([1, 2])
- @pytest.mark.parametrize('op', [operator.pow, ops.rpow])
- def test_pow_float(self, op, numeric_idx, box):
- # test power calculations both ways, GH#14973
- idx = numeric_idx
- expected = pd.Float64Index(op(idx.values, 2.0))
- idx = tm.box_expected(idx, box)
- expected = tm.box_expected(expected, box)
- result = op(idx, 2.0)
- tm.assert_equal(result, expected)
- def test_modulo(self, numeric_idx, box):
- # GH#9244
- idx = numeric_idx
- expected = Index(idx.values % 2)
- idx = tm.box_expected(idx, box)
- expected = tm.box_expected(expected, box)
- result = idx % 2
- tm.assert_equal(result, expected)
- def test_divmod_scalar(self, numeric_idx):
- idx = numeric_idx
- result = divmod(idx, 2)
- with np.errstate(all='ignore'):
- div, mod = divmod(idx.values, 2)
- expected = Index(div), Index(mod)
- for r, e in zip(result, expected):
- tm.assert_index_equal(r, e)
- def test_divmod_ndarray(self, numeric_idx):
- idx = numeric_idx
- other = np.ones(idx.values.shape, dtype=idx.values.dtype) * 2
- result = divmod(idx, other)
- with np.errstate(all='ignore'):
- div, mod = divmod(idx.values, other)
- expected = Index(div), Index(mod)
- for r, e in zip(result, expected):
- tm.assert_index_equal(r, e)
- def test_divmod_series(self, numeric_idx):
- idx = numeric_idx
- other = np.ones(idx.values.shape, dtype=idx.values.dtype) * 2
- result = divmod(idx, Series(other))
- with np.errstate(all='ignore'):
- div, mod = divmod(idx.values, other)
- expected = Series(div), Series(mod)
- for r, e in zip(result, expected):
- tm.assert_series_equal(r, e)
- @pytest.mark.parametrize('other', [np.nan, 7, -23, 2.718, -3.14, np.inf])
- def test_ops_np_scalar(self, other):
- vals = np.random.randn(5, 3)
- f = lambda x: pd.DataFrame(x, index=list('ABCDE'),
- columns=['jim', 'joe', 'jolie'])
- df = f(vals)
- tm.assert_frame_equal(df / np.array(other), f(vals / other))
- tm.assert_frame_equal(np.array(other) * df, f(vals * other))
- tm.assert_frame_equal(df + np.array(other), f(vals + other))
- tm.assert_frame_equal(np.array(other) - df, f(other - vals))
- # TODO: This came from series.test.test_operators, needs cleanup
- def test_operators_frame(self):
- # rpow does not work with DataFrame
- ts = tm.makeTimeSeries()
- ts.name = 'ts'
- df = pd.DataFrame({'A': ts})
- tm.assert_series_equal(ts + ts, ts + df['A'],
- check_names=False)
- tm.assert_series_equal(ts ** ts, ts ** df['A'],
- check_names=False)
- tm.assert_series_equal(ts < ts, ts < df['A'],
- check_names=False)
- tm.assert_series_equal(ts / ts, ts / df['A'],
- check_names=False)
- # TODO: this came from tests.series.test_analytics, needs cleannup and
- # de-duplication with test_modulo above
- def test_modulo2(self):
- with np.errstate(all='ignore'):
- # GH#3590, modulo as ints
- p = pd.DataFrame({'first': [3, 4, 5, 8], 'second': [0, 0, 0, 3]})
- result = p['first'] % p['second']
- expected = Series(p['first'].values % p['second'].values,
- dtype='float64')
- expected.iloc[0:3] = np.nan
- tm.assert_series_equal(result, expected)
- result = p['first'] % 0
- expected = Series(np.nan, index=p.index, name='first')
- tm.assert_series_equal(result, expected)
- p = p.astype('float64')
- result = p['first'] % p['second']
- expected = Series(p['first'].values % p['second'].values)
- tm.assert_series_equal(result, expected)
- p = p.astype('float64')
- result = p['first'] % p['second']
- result2 = p['second'] % p['first']
- assert not result.equals(result2)
- # GH#9144
- s = Series([0, 1])
- result = s % 0
- expected = Series([np.nan, np.nan])
- tm.assert_series_equal(result, expected)
- result = 0 % s
- expected = Series([np.nan, 0.0])
- tm.assert_series_equal(result, expected)
- class TestAdditionSubtraction(object):
- # __add__, __sub__, __radd__, __rsub__, __iadd__, __isub__
- # for non-timestamp/timedelta/period dtypes
- # TODO: This came from series.test.test_operators, needs cleanup
- def test_arith_ops_df_compat(self):
- # GH#1134
- s1 = pd.Series([1, 2, 3], index=list('ABC'), name='x')
- s2 = pd.Series([2, 2, 2], index=list('ABD'), name='x')
- exp = pd.Series([3.0, 4.0, np.nan, np.nan],
- index=list('ABCD'), name='x')
- tm.assert_series_equal(s1 + s2, exp)
- tm.assert_series_equal(s2 + s1, exp)
- exp = pd.DataFrame({'x': [3.0, 4.0, np.nan, np.nan]},
- index=list('ABCD'))
- tm.assert_frame_equal(s1.to_frame() + s2.to_frame(), exp)
- tm.assert_frame_equal(s2.to_frame() + s1.to_frame(), exp)
- # different length
- s3 = pd.Series([1, 2, 3], index=list('ABC'), name='x')
- s4 = pd.Series([2, 2, 2, 2], index=list('ABCD'), name='x')
- exp = pd.Series([3, 4, 5, np.nan],
- index=list('ABCD'), name='x')
- tm.assert_series_equal(s3 + s4, exp)
- tm.assert_series_equal(s4 + s3, exp)
- exp = pd.DataFrame({'x': [3, 4, 5, np.nan]},
- index=list('ABCD'))
- tm.assert_frame_equal(s3.to_frame() + s4.to_frame(), exp)
- tm.assert_frame_equal(s4.to_frame() + s3.to_frame(), exp)
- # TODO: This came from series.test.test_operators, needs cleanup
- def test_series_frame_radd_bug(self):
- # GH#353
- vals = pd.Series(tm.rands_array(5, 10))
- result = 'foo_' + vals
- expected = vals.map(lambda x: 'foo_' + x)
- tm.assert_series_equal(result, expected)
- frame = pd.DataFrame({'vals': vals})
- result = 'foo_' + frame
- expected = pd.DataFrame({'vals': vals.map(lambda x: 'foo_' + x)})
- tm.assert_frame_equal(result, expected)
- ts = tm.makeTimeSeries()
- ts.name = 'ts'
- # really raise this time
- now = pd.Timestamp.now().to_pydatetime()
- with pytest.raises(TypeError):
- now + ts
- with pytest.raises(TypeError):
- ts + now
- # TODO: This came from series.test.test_operators, needs cleanup
- def test_datetime64_with_index(self):
- # arithmetic integer ops with an index
- ser = pd.Series(np.random.randn(5))
- expected = ser - ser.index.to_series()
- result = ser - ser.index
- tm.assert_series_equal(result, expected)
- # GH#4629
- # arithmetic datetime64 ops with an index
- ser = pd.Series(pd.date_range('20130101', periods=5),
- index=pd.date_range('20130101', periods=5))
- expected = ser - ser.index.to_series()
- result = ser - ser.index
- tm.assert_series_equal(result, expected)
- with pytest.raises(TypeError):
- # GH#18850
- result = ser - ser.index.to_period()
- df = pd.DataFrame(np.random.randn(5, 2),
- index=pd.date_range('20130101', periods=5))
- df['date'] = pd.Timestamp('20130102')
- df['expected'] = df['date'] - df.index.to_series()
- df['result'] = df['date'] - df.index
- tm.assert_series_equal(df['result'], df['expected'], check_names=False)
- # TODO: taken from tests.frame.test_operators, needs cleanup
- def test_frame_operators(self):
- seriesd = tm.getSeriesData()
- frame = pd.DataFrame(seriesd)
- frame2 = pd.DataFrame(seriesd, columns=['D', 'C', 'B', 'A'])
- garbage = np.random.random(4)
- colSeries = pd.Series(garbage, index=np.array(frame.columns))
- idSum = frame + frame
- seriesSum = frame + colSeries
- for col, series in idSum.items():
- for idx, val in series.items():
- origVal = frame[col][idx] * 2
- if not np.isnan(val):
- assert val == origVal
- else:
- assert np.isnan(origVal)
- for col, series in seriesSum.items():
- for idx, val in series.items():
- origVal = frame[col][idx] + colSeries[col]
- if not np.isnan(val):
- assert val == origVal
- else:
- assert np.isnan(origVal)
- added = frame2 + frame2
- expected = frame2 * 2
- tm.assert_frame_equal(added, expected)
- df = pd.DataFrame({'a': ['a', None, 'b']})
- tm.assert_frame_equal(df + df,
- pd.DataFrame({'a': ['aa', np.nan, 'bb']}))
- # Test for issue #10181
- for dtype in ('float', 'int64'):
- frames = [
- pd.DataFrame(dtype=dtype),
- pd.DataFrame(columns=['A'], dtype=dtype),
- pd.DataFrame(index=[0], dtype=dtype),
- ]
- for df in frames:
- assert (df + df).equals(df)
- tm.assert_frame_equal(df + df, df)
- # TODO: taken from tests.series.test_operators; needs cleanup
- def test_series_operators(self):
- def _check_op(series, other, op, pos_only=False, check_dtype=True):
- left = np.abs(series) if pos_only else series
- right = np.abs(other) if pos_only else other
- cython_or_numpy = op(left, right)
- python = left.combine(right, op)
- tm.assert_series_equal(cython_or_numpy, python,
- check_dtype=check_dtype)
- def check(series, other):
- simple_ops = ['add', 'sub', 'mul', 'truediv', 'floordiv', 'mod']
- for opname in simple_ops:
- _check_op(series, other, getattr(operator, opname))
- _check_op(series, other, operator.pow, pos_only=True)
- _check_op(series, other, lambda x, y: operator.add(y, x))
- _check_op(series, other, lambda x, y: operator.sub(y, x))
- _check_op(series, other, lambda x, y: operator.truediv(y, x))
- _check_op(series, other, lambda x, y: operator.floordiv(y, x))
- _check_op(series, other, lambda x, y: operator.mul(y, x))
- _check_op(series, other, lambda x, y: operator.pow(y, x),
- pos_only=True)
- _check_op(series, other, lambda x, y: operator.mod(y, x))
- tser = tm.makeTimeSeries().rename('ts')
- check(tser, tser * 2)
- check(tser, tser * 0)
- check(tser, tser[::2])
- check(tser, 5)
- def check_comparators(series, other, check_dtype=True):
- _check_op(series, other, operator.gt, check_dtype=check_dtype)
- _check_op(series, other, operator.ge, check_dtype=check_dtype)
- _check_op(series, other, operator.eq, check_dtype=check_dtype)
- _check_op(series, other, operator.lt, check_dtype=check_dtype)
- _check_op(series, other, operator.le, check_dtype=check_dtype)
- check_comparators(tser, 5)
- check_comparators(tser, tser + 1, check_dtype=False)
- # TODO: taken from tests.series.test_operators; needs cleanup
- def test_divmod(self):
- def check(series, other):
- results = divmod(series, other)
- if isinstance(other, Iterable) and len(series) != len(other):
- # if the lengths don't match, this is the test where we use
- # `tser[::2]`. Pad every other value in `other_np` with nan.
- other_np = []
- for n in other:
- other_np.append(n)
- other_np.append(np.nan)
- else:
- other_np = other
- other_np = np.asarray(other_np)
- with np.errstate(all='ignore'):
- expecteds = divmod(series.values, np.asarray(other_np))
- for result, expected in zip(results, expecteds):
- # check the values, name, and index separately
- tm.assert_almost_equal(np.asarray(result), expected)
- assert result.name == series.name
- tm.assert_index_equal(result.index, series.index)
- tser = tm.makeTimeSeries().rename('ts')
- check(tser, tser * 2)
- check(tser, tser * 0)
- check(tser, tser[::2])
- check(tser, 5)
- class TestUFuncCompat(object):
- @pytest.mark.parametrize('holder', [pd.Int64Index, pd.UInt64Index,
- pd.Float64Index, pd.RangeIndex,
- pd.Series])
- def test_ufunc_compat(self, holder):
- box = pd.Series if holder is pd.Series else pd.Index
- if holder is pd.RangeIndex:
- idx = pd.RangeIndex(0, 5)
- else:
- idx = holder(np.arange(5, dtype='int64'))
- result = np.sin(idx)
- expected = box(np.sin(np.arange(5, dtype='int64')))
- tm.assert_equal(result, expected)
- @pytest.mark.parametrize('holder', [pd.Int64Index, pd.UInt64Index,
- pd.Float64Index, pd.Series])
- def test_ufunc_coercions(self, holder):
- idx = holder([1, 2, 3, 4, 5], name='x')
- box = pd.Series if holder is pd.Series else pd.Index
- result = np.sqrt(idx)
- assert result.dtype == 'f8' and isinstance(result, box)
- exp = pd.Float64Index(np.sqrt(np.array([1, 2, 3, 4, 5])), name='x')
- exp = tm.box_expected(exp, box)
- tm.assert_equal(result, exp)
- result = np.divide(idx, 2.)
- assert result.dtype == 'f8' and isinstance(result, box)
- exp = pd.Float64Index([0.5, 1., 1.5, 2., 2.5], name='x')
- exp = tm.box_expected(exp, box)
- tm.assert_equal(result, exp)
- # _evaluate_numeric_binop
- result = idx + 2.
- assert result.dtype == 'f8' and isinstance(result, box)
- exp = pd.Float64Index([3., 4., 5., 6., 7.], name='x')
- exp = tm.box_expected(exp, box)
- tm.assert_equal(result, exp)
- result = idx - 2.
- assert result.dtype == 'f8' and isinstance(result, box)
- exp = pd.Float64Index([-1., 0., 1., 2., 3.], name='x')
- exp = tm.box_expected(exp, box)
- tm.assert_equal(result, exp)
- result = idx * 1.
- assert result.dtype == 'f8' and isinstance(result, box)
- exp = pd.Float64Index([1., 2., 3., 4., 5.], name='x')
- exp = tm.box_expected(exp, box)
- tm.assert_equal(result, exp)
- result = idx / 2.
- assert result.dtype == 'f8' and isinstance(result, box)
- exp = pd.Float64Index([0.5, 1., 1.5, 2., 2.5], name='x')
- exp = tm.box_expected(exp, box)
- tm.assert_equal(result, exp)
- class TestObjectDtypeEquivalence(object):
- # Tests that arithmetic operations match operations executed elementwise
- @pytest.mark.parametrize('dtype', [None, object])
- def test_numarr_with_dtype_add_nan(self, dtype, box):
- ser = pd.Series([1, 2, 3], dtype=dtype)
- expected = pd.Series([np.nan, np.nan, np.nan], dtype=dtype)
- ser = tm.box_expected(ser, box)
- expected = tm.box_expected(expected, box)
- result = np.nan + ser
- tm.assert_equal(result, expected)
- result = ser + np.nan
- tm.assert_equal(result, expected)
- @pytest.mark.parametrize('dtype', [None, object])
- def test_numarr_with_dtype_add_int(self, dtype, box):
- ser = pd.Series([1, 2, 3], dtype=dtype)
- expected = pd.Series([2, 3, 4], dtype=dtype)
- ser = tm.box_expected(ser, box)
- expected = tm.box_expected(expected, box)
- result = 1 + ser
- tm.assert_equal(result, expected)
- result = ser + 1
- tm.assert_equal(result, expected)
- # TODO: moved from tests.series.test_operators; needs cleanup
- @pytest.mark.parametrize('op', [operator.add, operator.sub, operator.mul,
- operator.truediv, operator.floordiv])
- def test_operators_reverse_object(self, op):
- # GH#56
- arr = pd.Series(np.random.randn(10), index=np.arange(10), dtype=object)
- result = op(1., arr)
- expected = op(1., arr.astype(float))
- tm.assert_series_equal(result.astype(float), expected)
- class TestNumericArithmeticUnsorted(object):
- # Tests in this class have been moved from type-specific test modules
- # but not yet sorted, parametrized, and de-duplicated
- def check_binop(self, ops, scalars, idxs):
- for op in ops:
- for a, b in combinations(idxs, 2):
- result = op(a, b)
- expected = op(pd.Int64Index(a), pd.Int64Index(b))
- tm.assert_index_equal(result, expected)
- for idx in idxs:
- for scalar in scalars:
- result = op(idx, scalar)
- expected = op(pd.Int64Index(idx), scalar)
- tm.assert_index_equal(result, expected)
- def test_binops(self):
- ops = [operator.add, operator.sub, operator.mul, operator.floordiv,
- operator.truediv]
- scalars = [-1, 1, 2]
- idxs = [pd.RangeIndex(0, 10, 1), pd.RangeIndex(0, 20, 2),
- pd.RangeIndex(-10, 10, 2), pd.RangeIndex(5, -5, -1)]
- self.check_binop(ops, scalars, idxs)
- def test_binops_pow(self):
- # later versions of numpy don't allow powers of negative integers
- # so test separately
- # https://github.com/numpy/numpy/pull/8127
- ops = [pow]
- scalars = [1, 2]
- idxs = [pd.RangeIndex(0, 10, 1), pd.RangeIndex(0, 20, 2)]
- self.check_binop(ops, scalars, idxs)
- # TODO: mod, divmod?
- @pytest.mark.parametrize('op', [operator.add, operator.sub,
- operator.mul, operator.floordiv,
- operator.truediv, operator.pow])
- def test_arithmetic_with_frame_or_series(self, op):
- # check that we return NotImplemented when operating with Series
- # or DataFrame
- index = pd.RangeIndex(5)
- other = pd.Series(np.random.randn(5))
- expected = op(pd.Series(index), other)
- result = op(index, other)
- tm.assert_series_equal(result, expected)
- other = pd.DataFrame(np.random.randn(2, 5))
- expected = op(pd.DataFrame([index, index]), other)
- result = op(index, other)
- tm.assert_frame_equal(result, expected)
- def test_numeric_compat2(self):
- # validate that we are handling the RangeIndex overrides to numeric ops
- # and returning RangeIndex where possible
- idx = pd.RangeIndex(0, 10, 2)
- result = idx * 2
- expected = pd.RangeIndex(0, 20, 4)
- tm.assert_index_equal(result, expected, exact=True)
- result = idx + 2
- expected = pd.RangeIndex(2, 12, 2)
- tm.assert_index_equal(result, expected, exact=True)
- result = idx - 2
- expected = pd.RangeIndex(-2, 8, 2)
- tm.assert_index_equal(result, expected, exact=True)
- # truediv under PY3
- result = idx / 2
- if PY3:
- expected = pd.RangeIndex(0, 5, 1).astype('float64')
- else:
- expected = pd.RangeIndex(0, 5, 1)
- tm.assert_index_equal(result, expected, exact=True)
- result = idx / 4
- expected = pd.RangeIndex(0, 10, 2) / 4
- tm.assert_index_equal(result, expected, exact=True)
- result = idx // 1
- expected = idx
- tm.assert_index_equal(result, expected, exact=True)
- # __mul__
- result = idx * idx
- expected = Index(idx.values * idx.values)
- tm.assert_index_equal(result, expected, exact=True)
- # __pow__
- idx = pd.RangeIndex(0, 1000, 2)
- result = idx ** 2
- expected = idx._int64index ** 2
- tm.assert_index_equal(Index(result.values), expected, exact=True)
- # __floordiv__
- cases_exact = [
- (pd.RangeIndex(0, 1000, 2), 2, pd.RangeIndex(0, 500, 1)),
- (pd.RangeIndex(-99, -201, -3), -3, pd.RangeIndex(33, 67, 1)),
- (pd.RangeIndex(0, 1000, 1), 2,
- pd.RangeIndex(0, 1000, 1)._int64index // 2),
- (pd.RangeIndex(0, 100, 1), 2.0,
- pd.RangeIndex(0, 100, 1)._int64index // 2.0),
- (pd.RangeIndex(0), 50, pd.RangeIndex(0)),
- (pd.RangeIndex(2, 4, 2), 3, pd.RangeIndex(0, 1, 1)),
- (pd.RangeIndex(-5, -10, -6), 4, pd.RangeIndex(-2, -1, 1)),
- (pd.RangeIndex(-100, -200, 3), 2, pd.RangeIndex(0))]
- for idx, div, expected in cases_exact:
- tm.assert_index_equal(idx // div, expected, exact=True)
- @pytest.mark.parametrize('dtype', [np.int64, np.float64])
- @pytest.mark.parametrize('delta', [1, 0, -1])
- def test_addsub_arithmetic(self, dtype, delta):
- # GH#8142
- delta = dtype(delta)
- index = pd.Index([10, 11, 12], dtype=dtype)
- result = index + delta
- expected = pd.Index(index.values + delta, dtype=dtype)
- tm.assert_index_equal(result, expected)
- # this subtraction used to fail
- result = index - delta
- expected = pd.Index(index.values - delta, dtype=dtype)
- tm.assert_index_equal(result, expected)
- tm.assert_index_equal(index + index, 2 * index)
- tm.assert_index_equal(index - index, 0 * index)
- assert not (index - index).empty
|