test_arithmetics.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. import operator
  2. import numpy as np
  3. import pytest
  4. import pandas as pd
  5. from pandas.core.sparse.api import SparseDtype
  6. import pandas.util.testing as tm
  7. class TestSparseArrayArithmetics(object):
  8. _base = np.array
  9. _klass = pd.SparseArray
  10. def _assert(self, a, b):
  11. tm.assert_numpy_array_equal(a, b)
  12. def _check_numeric_ops(self, a, b, a_dense, b_dense):
  13. with np.errstate(invalid='ignore', divide='ignore'):
  14. # Unfortunately, trying to wrap the computation of each expected
  15. # value is with np.errstate() is too tedious.
  16. # sparse & sparse
  17. self._assert((a + b).to_dense(), a_dense + b_dense)
  18. self._assert((b + a).to_dense(), b_dense + a_dense)
  19. self._assert((a - b).to_dense(), a_dense - b_dense)
  20. self._assert((b - a).to_dense(), b_dense - a_dense)
  21. self._assert((a * b).to_dense(), a_dense * b_dense)
  22. self._assert((b * a).to_dense(), b_dense * a_dense)
  23. # pandas uses future division
  24. self._assert((a / b).to_dense(), a_dense * 1.0 / b_dense)
  25. self._assert((b / a).to_dense(), b_dense * 1.0 / a_dense)
  26. # ToDo: FIXME in GH 13843
  27. if not (self._base == pd.Series and
  28. a.dtype.subtype == np.dtype('int64')):
  29. self._assert((a // b).to_dense(), a_dense // b_dense)
  30. self._assert((b // a).to_dense(), b_dense // a_dense)
  31. self._assert((a % b).to_dense(), a_dense % b_dense)
  32. self._assert((b % a).to_dense(), b_dense % a_dense)
  33. self._assert((a ** b).to_dense(), a_dense ** b_dense)
  34. self._assert((b ** a).to_dense(), b_dense ** a_dense)
  35. # sparse & dense
  36. self._assert((a + b_dense).to_dense(), a_dense + b_dense)
  37. self._assert((b_dense + a).to_dense(), b_dense + a_dense)
  38. self._assert((a - b_dense).to_dense(), a_dense - b_dense)
  39. self._assert((b_dense - a).to_dense(), b_dense - a_dense)
  40. self._assert((a * b_dense).to_dense(), a_dense * b_dense)
  41. self._assert((b_dense * a).to_dense(), b_dense * a_dense)
  42. # pandas uses future division
  43. self._assert((a / b_dense).to_dense(), a_dense * 1.0 / b_dense)
  44. self._assert((b_dense / a).to_dense(), b_dense * 1.0 / a_dense)
  45. # ToDo: FIXME in GH 13843
  46. if not (self._base == pd.Series and
  47. a.dtype.subtype == np.dtype('int64')):
  48. self._assert((a // b_dense).to_dense(), a_dense // b_dense)
  49. self._assert((b_dense // a).to_dense(), b_dense // a_dense)
  50. self._assert((a % b_dense).to_dense(), a_dense % b_dense)
  51. self._assert((b_dense % a).to_dense(), b_dense % a_dense)
  52. self._assert((a ** b_dense).to_dense(), a_dense ** b_dense)
  53. self._assert((b_dense ** a).to_dense(), b_dense ** a_dense)
  54. def _check_bool_result(self, res):
  55. assert isinstance(res, self._klass)
  56. assert isinstance(res.dtype, SparseDtype)
  57. assert res.dtype.subtype == np.bool
  58. assert isinstance(res.fill_value, bool)
  59. def _check_comparison_ops(self, a, b, a_dense, b_dense):
  60. with np.errstate(invalid='ignore'):
  61. # Unfortunately, trying to wrap the computation of each expected
  62. # value is with np.errstate() is too tedious.
  63. #
  64. # sparse & sparse
  65. self._check_bool_result(a == b)
  66. self._assert((a == b).to_dense(), a_dense == b_dense)
  67. self._check_bool_result(a != b)
  68. self._assert((a != b).to_dense(), a_dense != b_dense)
  69. self._check_bool_result(a >= b)
  70. self._assert((a >= b).to_dense(), a_dense >= b_dense)
  71. self._check_bool_result(a <= b)
  72. self._assert((a <= b).to_dense(), a_dense <= b_dense)
  73. self._check_bool_result(a > b)
  74. self._assert((a > b).to_dense(), a_dense > b_dense)
  75. self._check_bool_result(a < b)
  76. self._assert((a < b).to_dense(), a_dense < b_dense)
  77. # sparse & dense
  78. self._check_bool_result(a == b_dense)
  79. self._assert((a == b_dense).to_dense(), a_dense == b_dense)
  80. self._check_bool_result(a != b_dense)
  81. self._assert((a != b_dense).to_dense(), a_dense != b_dense)
  82. self._check_bool_result(a >= b_dense)
  83. self._assert((a >= b_dense).to_dense(), a_dense >= b_dense)
  84. self._check_bool_result(a <= b_dense)
  85. self._assert((a <= b_dense).to_dense(), a_dense <= b_dense)
  86. self._check_bool_result(a > b_dense)
  87. self._assert((a > b_dense).to_dense(), a_dense > b_dense)
  88. self._check_bool_result(a < b_dense)
  89. self._assert((a < b_dense).to_dense(), a_dense < b_dense)
  90. def _check_logical_ops(self, a, b, a_dense, b_dense):
  91. # sparse & sparse
  92. self._check_bool_result(a & b)
  93. self._assert((a & b).to_dense(), a_dense & b_dense)
  94. self._check_bool_result(a | b)
  95. self._assert((a | b).to_dense(), a_dense | b_dense)
  96. # sparse & dense
  97. self._check_bool_result(a & b_dense)
  98. self._assert((a & b_dense).to_dense(), a_dense & b_dense)
  99. self._check_bool_result(a | b_dense)
  100. self._assert((a | b_dense).to_dense(), a_dense | b_dense)
  101. def test_float_scalar(self):
  102. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  103. for kind in ['integer', 'block']:
  104. a = self._klass(values, kind=kind)
  105. self._check_numeric_ops(a, 1, values, 1)
  106. self._check_numeric_ops(a, 0, values, 0)
  107. self._check_numeric_ops(a, 3, values, 3)
  108. a = self._klass(values, kind=kind, fill_value=0)
  109. self._check_numeric_ops(a, 1, values, 1)
  110. self._check_numeric_ops(a, 0, values, 0)
  111. self._check_numeric_ops(a, 3, values, 3)
  112. a = self._klass(values, kind=kind, fill_value=2)
  113. self._check_numeric_ops(a, 1, values, 1)
  114. self._check_numeric_ops(a, 0, values, 0)
  115. self._check_numeric_ops(a, 3, values, 3)
  116. def test_float_scalar_comparison(self):
  117. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  118. for kind in ['integer', 'block']:
  119. a = self._klass(values, kind=kind)
  120. self._check_comparison_ops(a, 1, values, 1)
  121. self._check_comparison_ops(a, 0, values, 0)
  122. self._check_comparison_ops(a, 3, values, 3)
  123. a = self._klass(values, kind=kind, fill_value=0)
  124. self._check_comparison_ops(a, 1, values, 1)
  125. self._check_comparison_ops(a, 0, values, 0)
  126. self._check_comparison_ops(a, 3, values, 3)
  127. a = self._klass(values, kind=kind, fill_value=2)
  128. self._check_comparison_ops(a, 1, values, 1)
  129. self._check_comparison_ops(a, 0, values, 0)
  130. self._check_comparison_ops(a, 3, values, 3)
  131. def test_float_same_index(self):
  132. # when sp_index are the same
  133. for kind in ['integer', 'block']:
  134. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  135. rvalues = self._base([np.nan, 2, 3, 4, np.nan, 0, 1, 3, 2, np.nan])
  136. a = self._klass(values, kind=kind)
  137. b = self._klass(rvalues, kind=kind)
  138. self._check_numeric_ops(a, b, values, rvalues)
  139. values = self._base([0., 1., 2., 6., 0., 0., 1., 2., 1., 0.])
  140. rvalues = self._base([0., 2., 3., 4., 0., 0., 1., 3., 2., 0.])
  141. a = self._klass(values, kind=kind, fill_value=0)
  142. b = self._klass(rvalues, kind=kind, fill_value=0)
  143. self._check_numeric_ops(a, b, values, rvalues)
  144. def test_float_same_index_comparison(self):
  145. # when sp_index are the same
  146. for kind in ['integer', 'block']:
  147. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  148. rvalues = self._base([np.nan, 2, 3, 4, np.nan, 0, 1, 3, 2, np.nan])
  149. a = self._klass(values, kind=kind)
  150. b = self._klass(rvalues, kind=kind)
  151. self._check_comparison_ops(a, b, values, rvalues)
  152. values = self._base([0., 1., 2., 6., 0., 0., 1., 2., 1., 0.])
  153. rvalues = self._base([0., 2., 3., 4., 0., 0., 1., 3., 2., 0.])
  154. a = self._klass(values, kind=kind, fill_value=0)
  155. b = self._klass(rvalues, kind=kind, fill_value=0)
  156. self._check_comparison_ops(a, b, values, rvalues)
  157. def test_float_array(self):
  158. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  159. rvalues = self._base([2, np.nan, 2, 3, np.nan, 0, 1, 5, 2, np.nan])
  160. for kind in ['integer', 'block']:
  161. a = self._klass(values, kind=kind)
  162. b = self._klass(rvalues, kind=kind)
  163. self._check_numeric_ops(a, b, values, rvalues)
  164. self._check_numeric_ops(a, b * 0, values, rvalues * 0)
  165. a = self._klass(values, kind=kind, fill_value=0)
  166. b = self._klass(rvalues, kind=kind)
  167. self._check_numeric_ops(a, b, values, rvalues)
  168. a = self._klass(values, kind=kind, fill_value=0)
  169. b = self._klass(rvalues, kind=kind, fill_value=0)
  170. self._check_numeric_ops(a, b, values, rvalues)
  171. a = self._klass(values, kind=kind, fill_value=1)
  172. b = self._klass(rvalues, kind=kind, fill_value=2)
  173. self._check_numeric_ops(a, b, values, rvalues)
  174. def test_float_array_different_kind(self):
  175. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  176. rvalues = self._base([2, np.nan, 2, 3, np.nan, 0, 1, 5, 2, np.nan])
  177. a = self._klass(values, kind='integer')
  178. b = self._klass(rvalues, kind='block')
  179. self._check_numeric_ops(a, b, values, rvalues)
  180. self._check_numeric_ops(a, b * 0, values, rvalues * 0)
  181. a = self._klass(values, kind='integer', fill_value=0)
  182. b = self._klass(rvalues, kind='block')
  183. self._check_numeric_ops(a, b, values, rvalues)
  184. a = self._klass(values, kind='integer', fill_value=0)
  185. b = self._klass(rvalues, kind='block', fill_value=0)
  186. self._check_numeric_ops(a, b, values, rvalues)
  187. a = self._klass(values, kind='integer', fill_value=1)
  188. b = self._klass(rvalues, kind='block', fill_value=2)
  189. self._check_numeric_ops(a, b, values, rvalues)
  190. def test_float_array_comparison(self):
  191. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  192. rvalues = self._base([2, np.nan, 2, 3, np.nan, 0, 1, 5, 2, np.nan])
  193. for kind in ['integer', 'block']:
  194. a = self._klass(values, kind=kind)
  195. b = self._klass(rvalues, kind=kind)
  196. self._check_comparison_ops(a, b, values, rvalues)
  197. self._check_comparison_ops(a, b * 0, values, rvalues * 0)
  198. a = self._klass(values, kind=kind, fill_value=0)
  199. b = self._klass(rvalues, kind=kind)
  200. self._check_comparison_ops(a, b, values, rvalues)
  201. a = self._klass(values, kind=kind, fill_value=0)
  202. b = self._klass(rvalues, kind=kind, fill_value=0)
  203. self._check_comparison_ops(a, b, values, rvalues)
  204. a = self._klass(values, kind=kind, fill_value=1)
  205. b = self._klass(rvalues, kind=kind, fill_value=2)
  206. self._check_comparison_ops(a, b, values, rvalues)
  207. def test_int_array(self):
  208. # have to specify dtype explicitly until fixing GH 667
  209. dtype = np.int64
  210. values = self._base([0, 1, 2, 0, 0, 0, 1, 2, 1, 0], dtype=dtype)
  211. rvalues = self._base([2, 0, 2, 3, 0, 0, 1, 5, 2, 0], dtype=dtype)
  212. for kind in ['integer', 'block']:
  213. a = self._klass(values, dtype=dtype, kind=kind)
  214. assert a.dtype == SparseDtype(dtype)
  215. b = self._klass(rvalues, dtype=dtype, kind=kind)
  216. assert b.dtype == SparseDtype(dtype)
  217. self._check_numeric_ops(a, b, values, rvalues)
  218. self._check_numeric_ops(a, b * 0, values, rvalues * 0)
  219. a = self._klass(values, fill_value=0, dtype=dtype, kind=kind)
  220. assert a.dtype == SparseDtype(dtype)
  221. b = self._klass(rvalues, dtype=dtype, kind=kind)
  222. assert b.dtype == SparseDtype(dtype)
  223. self._check_numeric_ops(a, b, values, rvalues)
  224. a = self._klass(values, fill_value=0, dtype=dtype, kind=kind)
  225. assert a.dtype == SparseDtype(dtype)
  226. b = self._klass(rvalues, fill_value=0, dtype=dtype, kind=kind)
  227. assert b.dtype == SparseDtype(dtype)
  228. self._check_numeric_ops(a, b, values, rvalues)
  229. a = self._klass(values, fill_value=1, dtype=dtype, kind=kind)
  230. assert a.dtype == SparseDtype(dtype, fill_value=1)
  231. b = self._klass(rvalues, fill_value=2, dtype=dtype, kind=kind)
  232. assert b.dtype == SparseDtype(dtype, fill_value=2)
  233. self._check_numeric_ops(a, b, values, rvalues)
  234. def test_int_array_comparison(self):
  235. # int32 NI ATM
  236. for dtype in ['int64']:
  237. values = self._base([0, 1, 2, 0, 0, 0, 1, 2, 1, 0], dtype=dtype)
  238. rvalues = self._base([2, 0, 2, 3, 0, 0, 1, 5, 2, 0], dtype=dtype)
  239. for kind in ['integer', 'block']:
  240. a = self._klass(values, dtype=dtype, kind=kind)
  241. b = self._klass(rvalues, dtype=dtype, kind=kind)
  242. self._check_comparison_ops(a, b, values, rvalues)
  243. self._check_comparison_ops(a, b * 0, values, rvalues * 0)
  244. a = self._klass(values, dtype=dtype, kind=kind, fill_value=0)
  245. b = self._klass(rvalues, dtype=dtype, kind=kind)
  246. self._check_comparison_ops(a, b, values, rvalues)
  247. a = self._klass(values, dtype=dtype, kind=kind, fill_value=0)
  248. b = self._klass(rvalues, dtype=dtype, kind=kind, fill_value=0)
  249. self._check_comparison_ops(a, b, values, rvalues)
  250. a = self._klass(values, dtype=dtype, kind=kind, fill_value=1)
  251. b = self._klass(rvalues, dtype=dtype, kind=kind, fill_value=2)
  252. self._check_comparison_ops(a, b, values, rvalues)
  253. def test_bool_same_index(self):
  254. # GH 14000
  255. # when sp_index are the same
  256. for kind in ['integer', 'block']:
  257. values = self._base([True, False, True, True], dtype=np.bool)
  258. rvalues = self._base([True, False, True, True], dtype=np.bool)
  259. for fill_value in [True, False, np.nan]:
  260. a = self._klass(values, kind=kind, dtype=np.bool,
  261. fill_value=fill_value)
  262. b = self._klass(rvalues, kind=kind, dtype=np.bool,
  263. fill_value=fill_value)
  264. self._check_logical_ops(a, b, values, rvalues)
  265. def test_bool_array_logical(self):
  266. # GH 14000
  267. # when sp_index are the same
  268. for kind in ['integer', 'block']:
  269. values = self._base([True, False, True, False, True, True],
  270. dtype=np.bool)
  271. rvalues = self._base([True, False, False, True, False, True],
  272. dtype=np.bool)
  273. for fill_value in [True, False, np.nan]:
  274. a = self._klass(values, kind=kind, dtype=np.bool,
  275. fill_value=fill_value)
  276. b = self._klass(rvalues, kind=kind, dtype=np.bool,
  277. fill_value=fill_value)
  278. self._check_logical_ops(a, b, values, rvalues)
  279. def test_mixed_array_float_int(self):
  280. for rdtype in ['int64']:
  281. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  282. rvalues = self._base([2, 0, 2, 3, 0, 0, 1, 5, 2, 0], dtype=rdtype)
  283. for kind in ['integer', 'block']:
  284. a = self._klass(values, kind=kind)
  285. b = self._klass(rvalues, kind=kind)
  286. assert b.dtype == SparseDtype(rdtype)
  287. self._check_numeric_ops(a, b, values, rvalues)
  288. self._check_numeric_ops(a, b * 0, values, rvalues * 0)
  289. a = self._klass(values, kind=kind, fill_value=0)
  290. b = self._klass(rvalues, kind=kind)
  291. assert b.dtype == SparseDtype(rdtype)
  292. self._check_numeric_ops(a, b, values, rvalues)
  293. a = self._klass(values, kind=kind, fill_value=0)
  294. b = self._klass(rvalues, kind=kind, fill_value=0)
  295. assert b.dtype == SparseDtype(rdtype)
  296. self._check_numeric_ops(a, b, values, rvalues)
  297. a = self._klass(values, kind=kind, fill_value=1)
  298. b = self._klass(rvalues, kind=kind, fill_value=2)
  299. assert b.dtype == SparseDtype(rdtype, fill_value=2)
  300. self._check_numeric_ops(a, b, values, rvalues)
  301. def test_mixed_array_comparison(self):
  302. # int32 NI ATM
  303. for rdtype in ['int64']:
  304. values = self._base([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan])
  305. rvalues = self._base([2, 0, 2, 3, 0, 0, 1, 5, 2, 0], dtype=rdtype)
  306. for kind in ['integer', 'block']:
  307. a = self._klass(values, kind=kind)
  308. b = self._klass(rvalues, kind=kind)
  309. assert b.dtype == SparseDtype(rdtype)
  310. self._check_comparison_ops(a, b, values, rvalues)
  311. self._check_comparison_ops(a, b * 0, values, rvalues * 0)
  312. a = self._klass(values, kind=kind, fill_value=0)
  313. b = self._klass(rvalues, kind=kind)
  314. assert b.dtype == SparseDtype(rdtype)
  315. self._check_comparison_ops(a, b, values, rvalues)
  316. a = self._klass(values, kind=kind, fill_value=0)
  317. b = self._klass(rvalues, kind=kind, fill_value=0)
  318. assert b.dtype == SparseDtype(rdtype)
  319. self._check_comparison_ops(a, b, values, rvalues)
  320. a = self._klass(values, kind=kind, fill_value=1)
  321. b = self._klass(rvalues, kind=kind, fill_value=2)
  322. assert b.dtype == SparseDtype(rdtype, fill_value=2)
  323. self._check_comparison_ops(a, b, values, rvalues)
  324. class TestSparseSeriesArithmetic(TestSparseArrayArithmetics):
  325. _base = pd.Series
  326. _klass = pd.SparseSeries
  327. def _assert(self, a, b):
  328. tm.assert_series_equal(a, b)
  329. def test_alignment(self):
  330. da = pd.Series(np.arange(4))
  331. db = pd.Series(np.arange(4), index=[1, 2, 3, 4])
  332. sa = pd.SparseSeries(np.arange(4), dtype=np.int64, fill_value=0)
  333. sb = pd.SparseSeries(np.arange(4), index=[1, 2, 3, 4],
  334. dtype=np.int64, fill_value=0)
  335. self._check_numeric_ops(sa, sb, da, db)
  336. sa = pd.SparseSeries(np.arange(4), dtype=np.int64, fill_value=np.nan)
  337. sb = pd.SparseSeries(np.arange(4), index=[1, 2, 3, 4],
  338. dtype=np.int64, fill_value=np.nan)
  339. self._check_numeric_ops(sa, sb, da, db)
  340. da = pd.Series(np.arange(4))
  341. db = pd.Series(np.arange(4), index=[10, 11, 12, 13])
  342. sa = pd.SparseSeries(np.arange(4), dtype=np.int64, fill_value=0)
  343. sb = pd.SparseSeries(np.arange(4), index=[10, 11, 12, 13],
  344. dtype=np.int64, fill_value=0)
  345. self._check_numeric_ops(sa, sb, da, db)
  346. sa = pd.SparseSeries(np.arange(4), dtype=np.int64, fill_value=np.nan)
  347. sb = pd.SparseSeries(np.arange(4), index=[10, 11, 12, 13],
  348. dtype=np.int64, fill_value=np.nan)
  349. self._check_numeric_ops(sa, sb, da, db)
  350. @pytest.mark.parametrize("op", [
  351. operator.eq,
  352. operator.add,
  353. ])
  354. def test_with_list(op):
  355. arr = pd.SparseArray([0, 1], fill_value=0)
  356. result = op(arr, [0, 1])
  357. expected = op(arr, pd.SparseArray([0, 1]))
  358. tm.assert_sp_array_equal(result, expected)
  359. @pytest.mark.parametrize('ufunc', [
  360. np.abs, np.exp,
  361. ])
  362. @pytest.mark.parametrize('arr', [
  363. pd.SparseArray([0, 0, -1, 1]),
  364. pd.SparseArray([None, None, -1, 1]),
  365. ])
  366. def test_ufuncs(ufunc, arr):
  367. result = ufunc(arr)
  368. fill_value = ufunc(arr.fill_value)
  369. expected = pd.SparseArray(ufunc(np.asarray(arr)), fill_value=fill_value)
  370. tm.assert_sp_array_equal(result, expected)
  371. @pytest.mark.parametrize("a, b", [
  372. (pd.SparseArray([0, 0, 0]), np.array([0, 1, 2])),
  373. (pd.SparseArray([0, 0, 0], fill_value=1), np.array([0, 1, 2])),
  374. (pd.SparseArray([0, 0, 0], fill_value=1), np.array([0, 1, 2])),
  375. (pd.SparseArray([0, 0, 0], fill_value=1), np.array([0, 1, 2])),
  376. (pd.SparseArray([0, 0, 0], fill_value=1), np.array([0, 1, 2])),
  377. ])
  378. @pytest.mark.parametrize("ufunc", [
  379. np.add,
  380. np.greater,
  381. ])
  382. def test_binary_ufuncs(ufunc, a, b):
  383. # can't say anything about fill value here.
  384. result = ufunc(a, b)
  385. expected = ufunc(np.asarray(a), np.asarray(b))
  386. assert isinstance(result, pd.SparseArray)
  387. tm.assert_numpy_array_equal(np.asarray(result), expected)
  388. def test_ndarray_inplace():
  389. sparray = pd.SparseArray([0, 2, 0, 0])
  390. ndarray = np.array([0, 1, 2, 3])
  391. ndarray += sparray
  392. expected = np.array([0, 3, 2, 3])
  393. tm.assert_numpy_array_equal(ndarray, expected)
  394. def test_sparray_inplace():
  395. sparray = pd.SparseArray([0, 2, 0, 0])
  396. ndarray = np.array([0, 1, 2, 3])
  397. sparray += ndarray
  398. expected = pd.SparseArray([0, 3, 2, 3], fill_value=0)
  399. tm.assert_sp_array_equal(sparray, expected)
  400. @pytest.mark.parametrize("fill_value", [True, False])
  401. def test_invert(fill_value):
  402. arr = np.array([True, False, False, True])
  403. sparray = pd.SparseArray(arr, fill_value=fill_value)
  404. result = ~sparray
  405. expected = pd.SparseArray(~arr, fill_value=not fill_value)
  406. tm.assert_sp_array_equal(result, expected)
  407. @pytest.mark.parametrize("fill_value", [0, np.nan])
  408. @pytest.mark.parametrize("op", [operator.pos, operator.neg])
  409. def test_unary_op(op, fill_value):
  410. arr = np.array([0, 1, np.nan, 2])
  411. sparray = pd.SparseArray(arr, fill_value=fill_value)
  412. result = op(sparray)
  413. expected = pd.SparseArray(op(arr), fill_value=op(fill_value))
  414. tm.assert_sp_array_equal(result, expected)