test_operators.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. # -*- coding: utf-8 -*-
  2. from __future__ import print_function
  3. from decimal import Decimal
  4. import operator
  5. import numpy as np
  6. import pytest
  7. from pandas.compat import range
  8. import pandas as pd
  9. from pandas import DataFrame, MultiIndex, Series, compat
  10. import pandas.core.common as com
  11. from pandas.tests.frame.common import TestData, _check_mixed_float
  12. import pandas.util.testing as tm
  13. from pandas.util.testing import (
  14. assert_frame_equal, assert_numpy_array_equal, assert_series_equal)
  15. class TestDataFrameUnaryOperators(object):
  16. # __pos__, __neg__, __inv__
  17. @pytest.mark.parametrize('df,expected', [
  18. (pd.DataFrame({'a': [-1, 1]}), pd.DataFrame({'a': [1, -1]})),
  19. (pd.DataFrame({'a': [False, True]}),
  20. pd.DataFrame({'a': [True, False]})),
  21. (pd.DataFrame({'a': pd.Series(pd.to_timedelta([-1, 1]))}),
  22. pd.DataFrame({'a': pd.Series(pd.to_timedelta([1, -1]))}))
  23. ])
  24. def test_neg_numeric(self, df, expected):
  25. assert_frame_equal(-df, expected)
  26. assert_series_equal(-df['a'], expected['a'])
  27. @pytest.mark.parametrize('df, expected', [
  28. (np.array([1, 2], dtype=object), np.array([-1, -2], dtype=object)),
  29. ([Decimal('1.0'), Decimal('2.0')], [Decimal('-1.0'), Decimal('-2.0')]),
  30. ])
  31. def test_neg_object(self, df, expected):
  32. # GH#21380
  33. df = pd.DataFrame({'a': df})
  34. expected = pd.DataFrame({'a': expected})
  35. assert_frame_equal(-df, expected)
  36. assert_series_equal(-df['a'], expected['a'])
  37. @pytest.mark.parametrize('df', [
  38. pd.DataFrame({'a': ['a', 'b']}),
  39. pd.DataFrame({'a': pd.to_datetime(['2017-01-22', '1970-01-01'])}),
  40. ])
  41. def test_neg_raises(self, df):
  42. with pytest.raises(TypeError):
  43. (- df)
  44. with pytest.raises(TypeError):
  45. (- df['a'])
  46. def test_invert(self):
  47. _seriesd = tm.getSeriesData()
  48. df = pd.DataFrame(_seriesd)
  49. assert_frame_equal(-(df < 0), ~(df < 0))
  50. @pytest.mark.parametrize('df', [
  51. pd.DataFrame({'a': [-1, 1]}),
  52. pd.DataFrame({'a': [False, True]}),
  53. pd.DataFrame({'a': pd.Series(pd.to_timedelta([-1, 1]))}),
  54. ])
  55. def test_pos_numeric(self, df):
  56. # GH#16073
  57. assert_frame_equal(+df, df)
  58. assert_series_equal(+df['a'], df['a'])
  59. @pytest.mark.parametrize('df', [
  60. # numpy changing behavior in the future
  61. pytest.param(pd.DataFrame({'a': ['a', 'b']}),
  62. marks=[pytest.mark.filterwarnings("ignore")]),
  63. pd.DataFrame({'a': np.array([-1, 2], dtype=object)}),
  64. pd.DataFrame({'a': [Decimal('-1.0'), Decimal('2.0')]}),
  65. ])
  66. def test_pos_object(self, df):
  67. # GH#21380
  68. assert_frame_equal(+df, df)
  69. assert_series_equal(+df['a'], df['a'])
  70. @pytest.mark.parametrize('df', [
  71. pd.DataFrame({'a': pd.to_datetime(['2017-01-22', '1970-01-01'])}),
  72. ])
  73. def test_pos_raises(self, df):
  74. with pytest.raises(TypeError):
  75. (+ df)
  76. with pytest.raises(TypeError):
  77. (+ df['a'])
  78. class TestDataFrameLogicalOperators(object):
  79. # &, |, ^
  80. def test_logical_ops_empty_frame(self):
  81. # GH#5808
  82. # empty frames, non-mixed dtype
  83. df = DataFrame(index=[1])
  84. result = df & df
  85. assert_frame_equal(result, df)
  86. result = df | df
  87. assert_frame_equal(result, df)
  88. df2 = DataFrame(index=[1, 2])
  89. result = df & df2
  90. assert_frame_equal(result, df2)
  91. dfa = DataFrame(index=[1], columns=['A'])
  92. result = dfa & dfa
  93. assert_frame_equal(result, dfa)
  94. def test_logical_ops_bool_frame(self):
  95. # GH#5808
  96. df1a_bool = DataFrame(True, index=[1], columns=['A'])
  97. result = df1a_bool & df1a_bool
  98. assert_frame_equal(result, df1a_bool)
  99. result = df1a_bool | df1a_bool
  100. assert_frame_equal(result, df1a_bool)
  101. def test_logical_ops_int_frame(self):
  102. # GH#5808
  103. df1a_int = DataFrame(1, index=[1], columns=['A'])
  104. df1a_bool = DataFrame(True, index=[1], columns=['A'])
  105. result = df1a_int | df1a_bool
  106. assert_frame_equal(result, df1a_int)
  107. def test_logical_ops_invalid(self):
  108. # GH#5808
  109. df1 = DataFrame(1.0, index=[1], columns=['A'])
  110. df2 = DataFrame(True, index=[1], columns=['A'])
  111. with pytest.raises(TypeError):
  112. df1 | df2
  113. df1 = DataFrame('foo', index=[1], columns=['A'])
  114. df2 = DataFrame(True, index=[1], columns=['A'])
  115. with pytest.raises(TypeError):
  116. df1 | df2
  117. def test_logical_operators(self):
  118. def _check_bin_op(op):
  119. result = op(df1, df2)
  120. expected = DataFrame(op(df1.values, df2.values), index=df1.index,
  121. columns=df1.columns)
  122. assert result.values.dtype == np.bool_
  123. assert_frame_equal(result, expected)
  124. def _check_unary_op(op):
  125. result = op(df1)
  126. expected = DataFrame(op(df1.values), index=df1.index,
  127. columns=df1.columns)
  128. assert result.values.dtype == np.bool_
  129. assert_frame_equal(result, expected)
  130. df1 = {'a': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True},
  131. 'b': {'a': False, 'b': True, 'c': False,
  132. 'd': False, 'e': False},
  133. 'c': {'a': False, 'b': False, 'c': True,
  134. 'd': False, 'e': False},
  135. 'd': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True},
  136. 'e': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}}
  137. df2 = {'a': {'a': True, 'b': False, 'c': True, 'd': False, 'e': False},
  138. 'b': {'a': False, 'b': True, 'c': False,
  139. 'd': False, 'e': False},
  140. 'c': {'a': True, 'b': False, 'c': True, 'd': False, 'e': False},
  141. 'd': {'a': False, 'b': False, 'c': False,
  142. 'd': True, 'e': False},
  143. 'e': {'a': False, 'b': False, 'c': False,
  144. 'd': False, 'e': True}}
  145. df1 = DataFrame(df1)
  146. df2 = DataFrame(df2)
  147. _check_bin_op(operator.and_)
  148. _check_bin_op(operator.or_)
  149. _check_bin_op(operator.xor)
  150. _check_unary_op(operator.inv) # TODO: belongs elsewhere
  151. def test_logical_with_nas(self):
  152. d = DataFrame({'a': [np.nan, False], 'b': [True, True]})
  153. # GH4947
  154. # bool comparisons should return bool
  155. result = d['a'] | d['b']
  156. expected = Series([False, True])
  157. assert_series_equal(result, expected)
  158. # GH4604, automatic casting here
  159. result = d['a'].fillna(False) | d['b']
  160. expected = Series([True, True])
  161. assert_series_equal(result, expected)
  162. result = d['a'].fillna(False, downcast=False) | d['b']
  163. expected = Series([True, True])
  164. assert_series_equal(result, expected)
  165. class TestDataFrameOperators(TestData):
  166. @pytest.mark.parametrize('op', [operator.add, operator.sub,
  167. operator.mul, operator.truediv])
  168. def test_operators_none_as_na(self, op):
  169. df = DataFrame({"col1": [2, 5.0, 123, None],
  170. "col2": [1, 2, 3, 4]}, dtype=object)
  171. # since filling converts dtypes from object, changed expected to be
  172. # object
  173. filled = df.fillna(np.nan)
  174. result = op(df, 3)
  175. expected = op(filled, 3).astype(object)
  176. expected[com.isna(expected)] = None
  177. assert_frame_equal(result, expected)
  178. result = op(df, df)
  179. expected = op(filled, filled).astype(object)
  180. expected[com.isna(expected)] = None
  181. assert_frame_equal(result, expected)
  182. result = op(df, df.fillna(7))
  183. assert_frame_equal(result, expected)
  184. result = op(df.fillna(7), df)
  185. assert_frame_equal(result, expected, check_dtype=False)
  186. @pytest.mark.parametrize('op,res', [('__eq__', False),
  187. ('__ne__', True)])
  188. # TODO: not sure what's correct here.
  189. @pytest.mark.filterwarnings("ignore:elementwise:FutureWarning")
  190. def test_logical_typeerror_with_non_valid(self, op, res):
  191. # we are comparing floats vs a string
  192. result = getattr(self.frame, op)('foo')
  193. assert bool(result.all().all()) is res
  194. def test_binary_ops_align(self):
  195. # test aligning binary ops
  196. # GH 6681
  197. index = MultiIndex.from_product([list('abc'),
  198. ['one', 'two', 'three'],
  199. [1, 2, 3]],
  200. names=['first', 'second', 'third'])
  201. df = DataFrame(np.arange(27 * 3).reshape(27, 3),
  202. index=index,
  203. columns=['value1', 'value2', 'value3']).sort_index()
  204. idx = pd.IndexSlice
  205. for op in ['add', 'sub', 'mul', 'div', 'truediv']:
  206. opa = getattr(operator, op, None)
  207. if opa is None:
  208. continue
  209. x = Series([1.0, 10.0, 100.0], [1, 2, 3])
  210. result = getattr(df, op)(x, level='third', axis=0)
  211. expected = pd.concat([opa(df.loc[idx[:, :, i], :], v)
  212. for i, v in x.iteritems()]).sort_index()
  213. assert_frame_equal(result, expected)
  214. x = Series([1.0, 10.0], ['two', 'three'])
  215. result = getattr(df, op)(x, level='second', axis=0)
  216. expected = (pd.concat([opa(df.loc[idx[:, i], :], v)
  217. for i, v in x.iteritems()])
  218. .reindex_like(df).sort_index())
  219. assert_frame_equal(result, expected)
  220. # GH9463 (alignment level of dataframe with series)
  221. midx = MultiIndex.from_product([['A', 'B'], ['a', 'b']])
  222. df = DataFrame(np.ones((2, 4), dtype='int64'), columns=midx)
  223. s = pd.Series({'a': 1, 'b': 2})
  224. df2 = df.copy()
  225. df2.columns.names = ['lvl0', 'lvl1']
  226. s2 = s.copy()
  227. s2.index.name = 'lvl1'
  228. # different cases of integer/string level names:
  229. res1 = df.mul(s, axis=1, level=1)
  230. res2 = df.mul(s2, axis=1, level=1)
  231. res3 = df2.mul(s, axis=1, level=1)
  232. res4 = df2.mul(s2, axis=1, level=1)
  233. res5 = df2.mul(s, axis=1, level='lvl1')
  234. res6 = df2.mul(s2, axis=1, level='lvl1')
  235. exp = DataFrame(np.array([[1, 2, 1, 2], [1, 2, 1, 2]], dtype='int64'),
  236. columns=midx)
  237. for res in [res1, res2]:
  238. assert_frame_equal(res, exp)
  239. exp.columns.names = ['lvl0', 'lvl1']
  240. for res in [res3, res4, res5, res6]:
  241. assert_frame_equal(res, exp)
  242. def test_dti_tz_convert_to_utc(self):
  243. base = pd.DatetimeIndex(['2011-01-01', '2011-01-02',
  244. '2011-01-03'], tz='UTC')
  245. idx1 = base.tz_convert('Asia/Tokyo')[:2]
  246. idx2 = base.tz_convert('US/Eastern')[1:]
  247. df1 = DataFrame({'A': [1, 2]}, index=idx1)
  248. df2 = DataFrame({'A': [1, 1]}, index=idx2)
  249. exp = DataFrame({'A': [np.nan, 3, np.nan]}, index=base)
  250. assert_frame_equal(df1 + df2, exp)
  251. def test_combineFrame(self):
  252. frame_copy = self.frame.reindex(self.frame.index[::2])
  253. del frame_copy['D']
  254. frame_copy['C'][:5] = np.nan
  255. added = self.frame + frame_copy
  256. indexer = added['A'].dropna().index
  257. exp = (self.frame['A'] * 2).copy()
  258. tm.assert_series_equal(added['A'].dropna(), exp.loc[indexer])
  259. exp.loc[~exp.index.isin(indexer)] = np.nan
  260. tm.assert_series_equal(added['A'], exp.loc[added['A'].index])
  261. assert np.isnan(added['C'].reindex(frame_copy.index)[:5]).all()
  262. # assert(False)
  263. assert np.isnan(added['D']).all()
  264. self_added = self.frame + self.frame
  265. tm.assert_index_equal(self_added.index, self.frame.index)
  266. added_rev = frame_copy + self.frame
  267. assert np.isnan(added['D']).all()
  268. assert np.isnan(added_rev['D']).all()
  269. # corner cases
  270. # empty
  271. plus_empty = self.frame + self.empty
  272. assert np.isnan(plus_empty.values).all()
  273. empty_plus = self.empty + self.frame
  274. assert np.isnan(empty_plus.values).all()
  275. empty_empty = self.empty + self.empty
  276. assert empty_empty.empty
  277. # out of order
  278. reverse = self.frame.reindex(columns=self.frame.columns[::-1])
  279. assert_frame_equal(reverse + self.frame, self.frame * 2)
  280. # mix vs float64, upcast
  281. added = self.frame + self.mixed_float
  282. _check_mixed_float(added, dtype='float64')
  283. added = self.mixed_float + self.frame
  284. _check_mixed_float(added, dtype='float64')
  285. # mix vs mix
  286. added = self.mixed_float + self.mixed_float2
  287. _check_mixed_float(added, dtype=dict(C=None))
  288. added = self.mixed_float2 + self.mixed_float
  289. _check_mixed_float(added, dtype=dict(C=None))
  290. # with int
  291. added = self.frame + self.mixed_int
  292. _check_mixed_float(added, dtype='float64')
  293. def test_combineSeries(self):
  294. # Series
  295. series = self.frame.xs(self.frame.index[0])
  296. added = self.frame + series
  297. for key, s in compat.iteritems(added):
  298. assert_series_equal(s, self.frame[key] + series[key])
  299. larger_series = series.to_dict()
  300. larger_series['E'] = 1
  301. larger_series = Series(larger_series)
  302. larger_added = self.frame + larger_series
  303. for key, s in compat.iteritems(self.frame):
  304. assert_series_equal(larger_added[key], s + series[key])
  305. assert 'E' in larger_added
  306. assert np.isnan(larger_added['E']).all()
  307. # no upcast needed
  308. added = self.mixed_float + series
  309. _check_mixed_float(added)
  310. # vs mix (upcast) as needed
  311. added = self.mixed_float + series.astype('float32')
  312. _check_mixed_float(added, dtype=dict(C=None))
  313. added = self.mixed_float + series.astype('float16')
  314. _check_mixed_float(added, dtype=dict(C=None))
  315. # these raise with numexpr.....as we are adding an int64 to an
  316. # uint64....weird vs int
  317. # added = self.mixed_int + (100*series).astype('int64')
  318. # _check_mixed_int(added, dtype = dict(A = 'int64', B = 'float64', C =
  319. # 'int64', D = 'int64'))
  320. # added = self.mixed_int + (100*series).astype('int32')
  321. # _check_mixed_int(added, dtype = dict(A = 'int32', B = 'float64', C =
  322. # 'int32', D = 'int64'))
  323. # TimeSeries
  324. ts = self.tsframe['A']
  325. # 10890
  326. # we no longer allow auto timeseries broadcasting
  327. # and require explicit broadcasting
  328. added = self.tsframe.add(ts, axis='index')
  329. for key, col in compat.iteritems(self.tsframe):
  330. result = col + ts
  331. assert_series_equal(added[key], result, check_names=False)
  332. assert added[key].name == key
  333. if col.name == ts.name:
  334. assert result.name == 'A'
  335. else:
  336. assert result.name is None
  337. smaller_frame = self.tsframe[:-5]
  338. smaller_added = smaller_frame.add(ts, axis='index')
  339. tm.assert_index_equal(smaller_added.index, self.tsframe.index)
  340. smaller_ts = ts[:-5]
  341. smaller_added2 = self.tsframe.add(smaller_ts, axis='index')
  342. assert_frame_equal(smaller_added, smaller_added2)
  343. # length 0, result is all-nan
  344. result = self.tsframe.add(ts[:0], axis='index')
  345. expected = DataFrame(np.nan, index=self.tsframe.index,
  346. columns=self.tsframe.columns)
  347. assert_frame_equal(result, expected)
  348. # Frame is all-nan
  349. result = self.tsframe[:0].add(ts, axis='index')
  350. expected = DataFrame(np.nan, index=self.tsframe.index,
  351. columns=self.tsframe.columns)
  352. assert_frame_equal(result, expected)
  353. # empty but with non-empty index
  354. frame = self.tsframe[:1].reindex(columns=[])
  355. result = frame.mul(ts, axis='index')
  356. assert len(result) == len(ts)
  357. def test_combineFunc(self):
  358. result = self.frame * 2
  359. tm.assert_numpy_array_equal(result.values, self.frame.values * 2)
  360. # vs mix
  361. result = self.mixed_float * 2
  362. for c, s in compat.iteritems(result):
  363. tm.assert_numpy_array_equal(
  364. s.values, self.mixed_float[c].values * 2)
  365. _check_mixed_float(result, dtype=dict(C=None))
  366. result = self.empty * 2
  367. assert result.index is self.empty.index
  368. assert len(result.columns) == 0
  369. def test_comparisons(self):
  370. df1 = tm.makeTimeDataFrame()
  371. df2 = tm.makeTimeDataFrame()
  372. row = self.simple.xs('a')
  373. ndim_5 = np.ones(df1.shape + (1, 1, 1))
  374. def test_comp(func):
  375. result = func(df1, df2)
  376. tm.assert_numpy_array_equal(result.values,
  377. func(df1.values, df2.values))
  378. with pytest.raises(ValueError, match='dim must be <= 2'):
  379. func(df1, ndim_5)
  380. result2 = func(self.simple, row)
  381. tm.assert_numpy_array_equal(result2.values,
  382. func(self.simple.values, row.values))
  383. result3 = func(self.frame, 0)
  384. tm.assert_numpy_array_equal(result3.values,
  385. func(self.frame.values, 0))
  386. msg = 'Can only compare identically-labeled DataFrame'
  387. with pytest.raises(ValueError, match=msg):
  388. func(self.simple, self.simple[:2])
  389. test_comp(operator.eq)
  390. test_comp(operator.ne)
  391. test_comp(operator.lt)
  392. test_comp(operator.gt)
  393. test_comp(operator.ge)
  394. test_comp(operator.le)
  395. def test_comparison_protected_from_errstate(self):
  396. missing_df = tm.makeDataFrame()
  397. missing_df.iloc[0]['A'] = np.nan
  398. with np.errstate(invalid='ignore'):
  399. expected = missing_df.values < 0
  400. with np.errstate(invalid='raise'):
  401. result = (missing_df < 0).values
  402. tm.assert_numpy_array_equal(result, expected)
  403. def test_boolean_comparison(self):
  404. # GH 4576
  405. # boolean comparisons with a tuple/list give unexpected results
  406. df = DataFrame(np.arange(6).reshape((3, 2)))
  407. b = np.array([2, 2])
  408. b_r = np.atleast_2d([2, 2])
  409. b_c = b_r.T
  410. lst = [2, 2, 2]
  411. tup = tuple(lst)
  412. # gt
  413. expected = DataFrame([[False, False], [False, True], [True, True]])
  414. result = df > b
  415. assert_frame_equal(result, expected)
  416. result = df.values > b
  417. assert_numpy_array_equal(result, expected.values)
  418. msg1d = 'Unable to coerce to Series, length must be 2: given 3'
  419. msg2d = 'Unable to coerce to DataFrame, shape must be'
  420. msg2db = 'operands could not be broadcast together with shapes'
  421. with pytest.raises(ValueError, match=msg1d):
  422. # wrong shape
  423. df > lst
  424. with pytest.raises(ValueError, match=msg1d):
  425. # wrong shape
  426. result = df > tup
  427. # broadcasts like ndarray (GH#23000)
  428. result = df > b_r
  429. assert_frame_equal(result, expected)
  430. result = df.values > b_r
  431. assert_numpy_array_equal(result, expected.values)
  432. with pytest.raises(ValueError, match=msg2d):
  433. df > b_c
  434. with pytest.raises(ValueError, match=msg2db):
  435. df.values > b_c
  436. # ==
  437. expected = DataFrame([[False, False], [True, False], [False, False]])
  438. result = df == b
  439. assert_frame_equal(result, expected)
  440. with pytest.raises(ValueError, match=msg1d):
  441. result = df == lst
  442. with pytest.raises(ValueError, match=msg1d):
  443. result = df == tup
  444. # broadcasts like ndarray (GH#23000)
  445. result = df == b_r
  446. assert_frame_equal(result, expected)
  447. result = df.values == b_r
  448. assert_numpy_array_equal(result, expected.values)
  449. with pytest.raises(ValueError, match=msg2d):
  450. df == b_c
  451. assert df.values.shape != b_c.shape
  452. # with alignment
  453. df = DataFrame(np.arange(6).reshape((3, 2)),
  454. columns=list('AB'), index=list('abc'))
  455. expected.index = df.index
  456. expected.columns = df.columns
  457. with pytest.raises(ValueError, match=msg1d):
  458. result = df == lst
  459. with pytest.raises(ValueError, match=msg1d):
  460. result = df == tup
  461. def test_combine_generic(self):
  462. df1 = self.frame
  463. df2 = self.frame.loc[self.frame.index[:-5], ['A', 'B', 'C']]
  464. combined = df1.combine(df2, np.add)
  465. combined2 = df2.combine(df1, np.add)
  466. assert combined['D'].isna().all()
  467. assert combined2['D'].isna().all()
  468. chunk = combined.loc[combined.index[:-5], ['A', 'B', 'C']]
  469. chunk2 = combined2.loc[combined2.index[:-5], ['A', 'B', 'C']]
  470. exp = self.frame.loc[self.frame.index[:-5],
  471. ['A', 'B', 'C']].reindex_like(chunk) * 2
  472. assert_frame_equal(chunk, exp)
  473. assert_frame_equal(chunk2, exp)
  474. def test_inplace_ops_alignment(self):
  475. # inplace ops / ops alignment
  476. # GH 8511
  477. columns = list('abcdefg')
  478. X_orig = DataFrame(np.arange(10 * len(columns))
  479. .reshape(-1, len(columns)),
  480. columns=columns, index=range(10))
  481. Z = 100 * X_orig.iloc[:, 1:-1].copy()
  482. block1 = list('bedcf')
  483. subs = list('bcdef')
  484. # add
  485. X = X_orig.copy()
  486. result1 = (X[block1] + Z).reindex(columns=subs)
  487. X[block1] += Z
  488. result2 = X.reindex(columns=subs)
  489. X = X_orig.copy()
  490. result3 = (X[block1] + Z[block1]).reindex(columns=subs)
  491. X[block1] += Z[block1]
  492. result4 = X.reindex(columns=subs)
  493. assert_frame_equal(result1, result2)
  494. assert_frame_equal(result1, result3)
  495. assert_frame_equal(result1, result4)
  496. # sub
  497. X = X_orig.copy()
  498. result1 = (X[block1] - Z).reindex(columns=subs)
  499. X[block1] -= Z
  500. result2 = X.reindex(columns=subs)
  501. X = X_orig.copy()
  502. result3 = (X[block1] - Z[block1]).reindex(columns=subs)
  503. X[block1] -= Z[block1]
  504. result4 = X.reindex(columns=subs)
  505. assert_frame_equal(result1, result2)
  506. assert_frame_equal(result1, result3)
  507. assert_frame_equal(result1, result4)
  508. def test_inplace_ops_identity(self):
  509. # GH 5104
  510. # make sure that we are actually changing the object
  511. s_orig = Series([1, 2, 3])
  512. df_orig = DataFrame(np.random.randint(0, 5, size=10).reshape(-1, 5))
  513. # no dtype change
  514. s = s_orig.copy()
  515. s2 = s
  516. s += 1
  517. assert_series_equal(s, s2)
  518. assert_series_equal(s_orig + 1, s)
  519. assert s is s2
  520. assert s._data is s2._data
  521. df = df_orig.copy()
  522. df2 = df
  523. df += 1
  524. assert_frame_equal(df, df2)
  525. assert_frame_equal(df_orig + 1, df)
  526. assert df is df2
  527. assert df._data is df2._data
  528. # dtype change
  529. s = s_orig.copy()
  530. s2 = s
  531. s += 1.5
  532. assert_series_equal(s, s2)
  533. assert_series_equal(s_orig + 1.5, s)
  534. df = df_orig.copy()
  535. df2 = df
  536. df += 1.5
  537. assert_frame_equal(df, df2)
  538. assert_frame_equal(df_orig + 1.5, df)
  539. assert df is df2
  540. assert df._data is df2._data
  541. # mixed dtype
  542. arr = np.random.randint(0, 10, size=5)
  543. df_orig = DataFrame({'A': arr.copy(), 'B': 'foo'})
  544. df = df_orig.copy()
  545. df2 = df
  546. df['A'] += 1
  547. expected = DataFrame({'A': arr.copy() + 1, 'B': 'foo'})
  548. assert_frame_equal(df, expected)
  549. assert_frame_equal(df2, expected)
  550. assert df._data is df2._data
  551. df = df_orig.copy()
  552. df2 = df
  553. df['A'] += 1.5
  554. expected = DataFrame({'A': arr.copy() + 1.5, 'B': 'foo'})
  555. assert_frame_equal(df, expected)
  556. assert_frame_equal(df2, expected)
  557. assert df._data is df2._data
  558. @pytest.mark.parametrize('op', ['add', 'and', 'div', 'floordiv', 'mod',
  559. 'mul', 'or', 'pow', 'sub', 'truediv',
  560. 'xor'])
  561. def test_inplace_ops_identity2(self, op):
  562. if compat.PY3 and op == 'div':
  563. return
  564. df = DataFrame({'a': [1., 2., 3.],
  565. 'b': [1, 2, 3]})
  566. operand = 2
  567. if op in ('and', 'or', 'xor'):
  568. # cannot use floats for boolean ops
  569. df['a'] = [True, False, True]
  570. df_copy = df.copy()
  571. iop = '__i{}__'.format(op)
  572. op = '__{}__'.format(op)
  573. # no id change and value is correct
  574. getattr(df, iop)(operand)
  575. expected = getattr(df_copy, op)(operand)
  576. assert_frame_equal(df, expected)
  577. expected = id(df)
  578. assert id(df) == expected
  579. def test_alignment_non_pandas(self):
  580. index = ['A', 'B', 'C']
  581. columns = ['X', 'Y', 'Z']
  582. df = pd.DataFrame(np.random.randn(3, 3), index=index, columns=columns)
  583. align = pd.core.ops._align_method_FRAME
  584. for val in [[1, 2, 3], (1, 2, 3), np.array([1, 2, 3], dtype=np.int64),
  585. range(1, 4)]:
  586. tm.assert_series_equal(align(df, val, 'index'),
  587. Series([1, 2, 3], index=df.index))
  588. tm.assert_series_equal(align(df, val, 'columns'),
  589. Series([1, 2, 3], index=df.columns))
  590. # length mismatch
  591. msg = 'Unable to coerce to Series, length must be 3: given 2'
  592. for val in [[1, 2], (1, 2), np.array([1, 2]), range(1, 3)]:
  593. with pytest.raises(ValueError, match=msg):
  594. align(df, val, 'index')
  595. with pytest.raises(ValueError, match=msg):
  596. align(df, val, 'columns')
  597. val = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
  598. tm.assert_frame_equal(align(df, val, 'index'),
  599. DataFrame(val, index=df.index,
  600. columns=df.columns))
  601. tm.assert_frame_equal(align(df, val, 'columns'),
  602. DataFrame(val, index=df.index,
  603. columns=df.columns))
  604. # shape mismatch
  605. msg = 'Unable to coerce to DataFrame, shape must be'
  606. val = np.array([[1, 2, 3], [4, 5, 6]])
  607. with pytest.raises(ValueError, match=msg):
  608. align(df, val, 'index')
  609. with pytest.raises(ValueError, match=msg):
  610. align(df, val, 'columns')
  611. val = np.zeros((3, 3, 3))
  612. with pytest.raises(ValueError):
  613. align(df, val, 'index')
  614. with pytest.raises(ValueError):
  615. align(df, val, 'columns')
  616. def test_no_warning(self, all_arithmetic_operators):
  617. df = pd.DataFrame({"A": [0., 0.], "B": [0., None]})
  618. b = df['B']
  619. with tm.assert_produces_warning(None):
  620. getattr(df, all_arithmetic_operators)(b, 0)