PageRenderTime 93ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/pandas/sparse/series.py

http://github.com/wesm/pandas
Python | 821 lines | 657 code | 51 blank | 113 comment | 31 complexity | 80f078246995928db571849d0b66ce64 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. """
  2. Data structures for sparse float data. Life is made simpler by dealing only
  3. with float64 data
  4. """
  5. # pylint: disable=E1101,E1103,W0231
  6. import numpy as np
  7. import warnings
  8. from pandas.types.missing import isnull
  9. from pandas.types.common import is_scalar
  10. from pandas.core.common import _values_from_object, _maybe_match_name
  11. from pandas.compat.numpy import function as nv
  12. from pandas.core.index import Index, _ensure_index, InvalidIndexError
  13. from pandas.core.series import Series
  14. from pandas.core.frame import DataFrame
  15. from pandas.core.internals import SingleBlockManager
  16. from pandas.core import generic
  17. import pandas.core.common as com
  18. import pandas.core.ops as ops
  19. import pandas.index as _index
  20. from pandas.util.decorators import Appender
  21. from pandas.sparse.array import (make_sparse, _sparse_array_op, SparseArray,
  22. _make_index)
  23. from pandas._sparse import BlockIndex, IntIndex
  24. import pandas._sparse as splib
  25. from pandas.sparse.scipy_sparse import (_sparse_series_to_coo,
  26. _coo_to_sparse_series)
  27. _shared_doc_kwargs = dict(klass='SparseSeries',
  28. axes_single_arg="{0, 'index'}")
  29. # -----------------------------------------------------------------------------
  30. # Wrapper function for Series arithmetic methods
  31. def _arith_method(op, name, str_rep=None, default_axis=None, fill_zeros=None,
  32. **eval_kwargs):
  33. """
  34. Wrapper function for Series arithmetic operations, to avoid
  35. code duplication.
  36. str_rep, default_axis, fill_zeros and eval_kwargs are not used, but are
  37. present for compatibility.
  38. """
  39. def wrapper(self, other):
  40. if isinstance(other, Series):
  41. if not isinstance(other, SparseSeries):
  42. other = other.to_sparse(fill_value=self.fill_value)
  43. return _sparse_series_op(self, other, op, name)
  44. elif isinstance(other, DataFrame):
  45. return NotImplemented
  46. elif is_scalar(other):
  47. new_values = op(self.values, other)
  48. return self._constructor(new_values,
  49. index=self.index,
  50. name=self.name)
  51. else: # pragma: no cover
  52. raise TypeError('operation with %s not supported' % type(other))
  53. wrapper.__name__ = name
  54. if name.startswith("__"):
  55. # strip special method names, e.g. `__add__` needs to be `add` when
  56. # passed to _sparse_series_op
  57. name = name[2:-2]
  58. return wrapper
  59. def _sparse_series_op(left, right, op, name):
  60. left, right = left.align(right, join='outer', copy=False)
  61. new_index = left.index
  62. new_name = _maybe_match_name(left, right)
  63. result = _sparse_array_op(left.values, right.values, op, name,
  64. series=True)
  65. return left._constructor(result, index=new_index, name=new_name)
  66. class SparseSeries(Series):
  67. """Data structure for labeled, sparse floating point data
  68. Parameters
  69. ----------
  70. data : {array-like, Series, SparseSeries, dict}
  71. kind : {'block', 'integer'}
  72. fill_value : float
  73. Defaults to NaN (code for missing)
  74. sparse_index : {BlockIndex, IntIndex}, optional
  75. Only if you have one. Mainly used internally
  76. Notes
  77. -----
  78. SparseSeries objects are immutable via the typical Python means. If you
  79. must change values, convert to dense, make your changes, then convert back
  80. to sparse
  81. """
  82. _subtyp = 'sparse_series'
  83. def __init__(self, data=None, index=None, sparse_index=None, kind='block',
  84. fill_value=None, name=None, dtype=None, copy=False,
  85. fastpath=False):
  86. # we are called internally, so short-circuit
  87. if fastpath:
  88. # data is an ndarray, index is defined
  89. if not isinstance(data, SingleBlockManager):
  90. data = SingleBlockManager(data, index, fastpath=True)
  91. if copy:
  92. data = data.copy()
  93. else:
  94. if data is None:
  95. data = []
  96. if isinstance(data, Series) and name is None:
  97. name = data.name
  98. is_sparse_array = isinstance(data, SparseArray)
  99. if fill_value is None:
  100. if is_sparse_array:
  101. fill_value = data.fill_value
  102. else:
  103. fill_value = np.nan
  104. if is_sparse_array:
  105. if isinstance(data, SparseSeries) and index is None:
  106. index = data.index.view()
  107. elif index is not None:
  108. assert (len(index) == len(data))
  109. sparse_index = data.sp_index
  110. data = np.asarray(data)
  111. elif isinstance(data, SparseSeries):
  112. if index is None:
  113. index = data.index.view()
  114. # extract the SingleBlockManager
  115. data = data._data
  116. elif isinstance(data, (Series, dict)):
  117. if index is None:
  118. index = data.index.view()
  119. data = Series(data)
  120. data, sparse_index = make_sparse(data, kind=kind,
  121. fill_value=fill_value)
  122. elif isinstance(data, (tuple, list, np.ndarray)):
  123. # array-like
  124. if sparse_index is None:
  125. data, sparse_index = make_sparse(data, kind=kind,
  126. fill_value=fill_value)
  127. else:
  128. assert (len(data) == sparse_index.npoints)
  129. elif isinstance(data, SingleBlockManager):
  130. if dtype is not None:
  131. data = data.astype(dtype)
  132. if index is None:
  133. index = data.index.view()
  134. else:
  135. data = data.reindex(index, copy=False)
  136. else:
  137. length = len(index)
  138. if data == fill_value or (isnull(data) and isnull(fill_value)):
  139. if kind == 'block':
  140. sparse_index = BlockIndex(length, [], [])
  141. else:
  142. sparse_index = IntIndex(length, [])
  143. data = np.array([])
  144. else:
  145. if kind == 'block':
  146. locs, lens = ([0], [length]) if length else ([], [])
  147. sparse_index = BlockIndex(length, locs, lens)
  148. else:
  149. sparse_index = IntIndex(length, index)
  150. v = data
  151. data = np.empty(length)
  152. data.fill(v)
  153. if index is None:
  154. index = com._default_index(sparse_index.length)
  155. index = _ensure_index(index)
  156. # create/copy the manager
  157. if isinstance(data, SingleBlockManager):
  158. if copy:
  159. data = data.copy()
  160. else:
  161. # create a sparse array
  162. if not isinstance(data, SparseArray):
  163. data = SparseArray(data, sparse_index=sparse_index,
  164. fill_value=fill_value, dtype=dtype,
  165. copy=copy)
  166. data = SingleBlockManager(data, index)
  167. generic.NDFrame.__init__(self, data)
  168. self.index = index
  169. self.name = name
  170. @property
  171. def values(self):
  172. """ return the array """
  173. return self.block.values
  174. def __array__(self, result=None):
  175. """ the array interface, return my values """
  176. return self.block.values
  177. def get_values(self):
  178. """ same as values """
  179. return self.block.to_dense().view()
  180. @property
  181. def block(self):
  182. return self._data._block
  183. @property
  184. def fill_value(self):
  185. return self.block.fill_value
  186. @fill_value.setter
  187. def fill_value(self, v):
  188. self.block.fill_value = v
  189. @property
  190. def sp_index(self):
  191. return self.block.sp_index
  192. @property
  193. def sp_values(self):
  194. return self.values.sp_values
  195. @property
  196. def npoints(self):
  197. return self.sp_index.npoints
  198. @classmethod
  199. def from_array(cls, arr, index=None, name=None, copy=False,
  200. fill_value=None, fastpath=False):
  201. """
  202. Simplified alternate constructor
  203. """
  204. return cls(arr, index=index, name=name, copy=copy,
  205. fill_value=fill_value, fastpath=fastpath)
  206. @property
  207. def _constructor(self):
  208. return SparseSeries
  209. @property
  210. def _constructor_expanddim(self):
  211. from pandas.sparse.api import SparseDataFrame
  212. return SparseDataFrame
  213. @property
  214. def kind(self):
  215. if isinstance(self.sp_index, BlockIndex):
  216. return 'block'
  217. elif isinstance(self.sp_index, IntIndex):
  218. return 'integer'
  219. def as_sparse_array(self, kind=None, fill_value=None, copy=False):
  220. """ return my self as a sparse array, do not copy by default """
  221. if fill_value is None:
  222. fill_value = self.fill_value
  223. if kind is None:
  224. kind = self.kind
  225. return SparseArray(self.values, sparse_index=self.sp_index,
  226. fill_value=fill_value, kind=kind, copy=copy)
  227. def __len__(self):
  228. return len(self.block)
  229. @property
  230. def shape(self):
  231. return self._data.shape
  232. def __unicode__(self):
  233. # currently, unicode is same as repr...fixes infinite loop
  234. series_rep = Series.__unicode__(self)
  235. rep = '%s\n%s' % (series_rep, repr(self.sp_index))
  236. return rep
  237. def __array_wrap__(self, result, context=None):
  238. """
  239. Gets called prior to a ufunc (and after)
  240. See SparseArray.__array_wrap__ for detail.
  241. """
  242. if isinstance(context, tuple) and len(context) == 3:
  243. ufunc, args, domain = context
  244. args = [getattr(a, 'fill_value', a) for a in args]
  245. fill_value = ufunc(self.fill_value, *args[1:])
  246. else:
  247. fill_value = self.fill_value
  248. return self._constructor(result, index=self.index,
  249. sparse_index=self.sp_index,
  250. fill_value=fill_value,
  251. copy=False).__finalize__(self)
  252. def __array_finalize__(self, obj):
  253. """
  254. Gets called after any ufunc or other array operations, necessary
  255. to pass on the index.
  256. """
  257. self.name = getattr(obj, 'name', None)
  258. self.fill_value = getattr(obj, 'fill_value', None)
  259. def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
  260. filter_type=None, **kwds):
  261. """ perform a reduction operation """
  262. return op(self.get_values(), skipna=skipna, **kwds)
  263. def __getstate__(self):
  264. # pickling
  265. return dict(_typ=self._typ, _subtyp=self._subtyp, _data=self._data,
  266. fill_value=self.fill_value, name=self.name)
  267. def _unpickle_series_compat(self, state):
  268. nd_state, own_state = state
  269. # recreate the ndarray
  270. data = np.empty(nd_state[1], dtype=nd_state[2])
  271. np.ndarray.__setstate__(data, nd_state)
  272. index, fill_value, sp_index = own_state[:3]
  273. name = None
  274. if len(own_state) > 3:
  275. name = own_state[3]
  276. # create a sparse array
  277. if not isinstance(data, SparseArray):
  278. data = SparseArray(data, sparse_index=sp_index,
  279. fill_value=fill_value, copy=False)
  280. # recreate
  281. data = SingleBlockManager(data, index, fastpath=True)
  282. generic.NDFrame.__init__(self, data)
  283. self._set_axis(0, index)
  284. self.name = name
  285. def __iter__(self):
  286. """ forward to the array """
  287. return iter(self.values)
  288. def _set_subtyp(self, is_all_dates):
  289. if is_all_dates:
  290. object.__setattr__(self, '_subtyp', 'sparse_time_series')
  291. else:
  292. object.__setattr__(self, '_subtyp', 'sparse_series')
  293. def _ixs(self, i, axis=0):
  294. """
  295. Return the i-th value or values in the SparseSeries by location
  296. Parameters
  297. ----------
  298. i : int, slice, or sequence of integers
  299. Returns
  300. -------
  301. value : scalar (int) or Series (slice, sequence)
  302. """
  303. label = self.index[i]
  304. if isinstance(label, Index):
  305. return self.take(i, axis=axis, convert=True)
  306. else:
  307. return self._get_val_at(i)
  308. def _get_val_at(self, loc):
  309. """ forward to the array """
  310. return self.block.values._get_val_at(loc)
  311. def __getitem__(self, key):
  312. try:
  313. return self.index.get_value(self, key)
  314. except InvalidIndexError:
  315. pass
  316. except KeyError:
  317. if isinstance(key, (int, np.integer)):
  318. return self._get_val_at(key)
  319. elif key is Ellipsis:
  320. return self
  321. raise Exception('Requested index not in this series!')
  322. except TypeError:
  323. # Could not hash item, must be array-like?
  324. pass
  325. key = _values_from_object(key)
  326. if self.index.nlevels > 1 and isinstance(key, tuple):
  327. # to handle MultiIndex labels
  328. key = self.index.get_loc(key)
  329. return self._constructor(self.values[key],
  330. index=self.index[key]).__finalize__(self)
  331. def _get_values(self, indexer):
  332. try:
  333. return self._constructor(self._data.get_slice(indexer),
  334. fastpath=True).__finalize__(self)
  335. except Exception:
  336. return self[indexer]
  337. def _set_with_engine(self, key, value):
  338. return self.set_value(key, value)
  339. def abs(self):
  340. """
  341. Return an object with absolute value taken. Only applicable to objects
  342. that are all numeric
  343. Returns
  344. -------
  345. abs: type of caller
  346. """
  347. return self._constructor(np.abs(self.values),
  348. index=self.index).__finalize__(self)
  349. def get(self, label, default=None):
  350. """
  351. Returns value occupying requested label, default to specified
  352. missing value if not present. Analogous to dict.get
  353. Parameters
  354. ----------
  355. label : object
  356. Label value looking for
  357. default : object, optional
  358. Value to return if label not in index
  359. Returns
  360. -------
  361. y : scalar
  362. """
  363. if label in self.index:
  364. loc = self.index.get_loc(label)
  365. return self._get_val_at(loc)
  366. else:
  367. return default
  368. def get_value(self, label, takeable=False):
  369. """
  370. Retrieve single value at passed index label
  371. Parameters
  372. ----------
  373. index : label
  374. takeable : interpret the index as indexers, default False
  375. Returns
  376. -------
  377. value : scalar value
  378. """
  379. loc = label if takeable is True else self.index.get_loc(label)
  380. return self._get_val_at(loc)
  381. def set_value(self, label, value, takeable=False):
  382. """
  383. Quickly set single value at passed label. If label is not contained, a
  384. new object is created with the label placed at the end of the result
  385. index
  386. Parameters
  387. ----------
  388. label : object
  389. Partial indexing with MultiIndex not allowed
  390. value : object
  391. Scalar value
  392. takeable : interpret the index as indexers, default False
  393. Notes
  394. -----
  395. This method *always* returns a new object. It is not particularly
  396. efficient but is provided for API compatibility with Series
  397. Returns
  398. -------
  399. series : SparseSeries
  400. """
  401. values = self.to_dense()
  402. # if the label doesn't exist, we will create a new object here
  403. # and possibily change the index
  404. new_values = values.set_value(label, value, takeable=takeable)
  405. if new_values is not None:
  406. values = new_values
  407. new_index = values.index
  408. values = SparseArray(values, fill_value=self.fill_value,
  409. kind=self.kind)
  410. self._data = SingleBlockManager(values, new_index)
  411. self._index = new_index
  412. def _set_values(self, key, value):
  413. # this might be inefficient as we have to recreate the sparse array
  414. # rather than setting individual elements, but have to convert
  415. # the passed slice/boolean that's in dense space into a sparse indexer
  416. # not sure how to do that!
  417. if isinstance(key, Series):
  418. key = key.values
  419. values = self.values.to_dense()
  420. values[key] = _index.convert_scalar(values, value)
  421. values = SparseArray(values, fill_value=self.fill_value,
  422. kind=self.kind)
  423. self._data = SingleBlockManager(values, self.index)
  424. def to_dense(self, sparse_only=False):
  425. """
  426. Convert SparseSeries to (dense) Series
  427. """
  428. if sparse_only:
  429. int_index = self.sp_index.to_int_index()
  430. index = self.index.take(int_index.indices)
  431. return Series(self.sp_values, index=index, name=self.name)
  432. else:
  433. return Series(self.values.to_dense(), index=self.index,
  434. name=self.name)
  435. @property
  436. def density(self):
  437. r = float(self.sp_index.npoints) / float(self.sp_index.length)
  438. return r
  439. def copy(self, deep=True):
  440. """
  441. Make a copy of the SparseSeries. Only the actual sparse values need to
  442. be copied
  443. """
  444. new_data = self._data
  445. if deep:
  446. new_data = self._data.copy()
  447. return self._constructor(new_data, sparse_index=self.sp_index,
  448. fill_value=self.fill_value).__finalize__(self)
  449. def reindex(self, index=None, method=None, copy=True, limit=None,
  450. **kwargs):
  451. """
  452. Conform SparseSeries to new Index
  453. See Series.reindex docstring for general behavior
  454. Returns
  455. -------
  456. reindexed : SparseSeries
  457. """
  458. new_index = _ensure_index(index)
  459. if self.index.equals(new_index):
  460. if copy:
  461. return self.copy()
  462. else:
  463. return self
  464. return self._constructor(self._data.reindex(new_index, method=method,
  465. limit=limit, copy=copy),
  466. index=new_index).__finalize__(self)
  467. def sparse_reindex(self, new_index):
  468. """
  469. Conform sparse values to new SparseIndex
  470. Parameters
  471. ----------
  472. new_index : {BlockIndex, IntIndex}
  473. Returns
  474. -------
  475. reindexed : SparseSeries
  476. """
  477. if not isinstance(new_index, splib.SparseIndex):
  478. raise TypeError('new index must be a SparseIndex')
  479. block = self.block.sparse_reindex(new_index)
  480. new_data = SingleBlockManager(block, self.index)
  481. return self._constructor(new_data, index=self.index,
  482. sparse_index=new_index,
  483. fill_value=self.fill_value).__finalize__(self)
  484. def take(self, indices, axis=0, convert=True, *args, **kwargs):
  485. """
  486. Sparse-compatible version of ndarray.take
  487. Returns
  488. -------
  489. taken : ndarray
  490. """
  491. convert = nv.validate_take_with_convert(convert, args, kwargs)
  492. new_values = SparseArray.take(self.values, indices)
  493. new_index = self.index.take(indices)
  494. return self._constructor(new_values,
  495. index=new_index).__finalize__(self)
  496. def cumsum(self, axis=0, *args, **kwargs):
  497. """
  498. Cumulative sum of values. Preserves locations of NaN values
  499. Returns
  500. -------
  501. cumsum : SparseSeries if `self` has a null `fill_value` and a
  502. generic Series otherwise
  503. """
  504. nv.validate_cumsum(args, kwargs)
  505. new_array = SparseArray.cumsum(self.values)
  506. if isinstance(new_array, SparseArray):
  507. return self._constructor(
  508. new_array, index=self.index,
  509. sparse_index=new_array.sp_index).__finalize__(self)
  510. # TODO: gh-12855 - return a SparseSeries here
  511. return Series(new_array, index=self.index).__finalize__(self)
  512. def dropna(self, axis=0, inplace=False, **kwargs):
  513. """
  514. Analogous to Series.dropna. If fill_value=NaN, returns a dense Series
  515. """
  516. # TODO: make more efficient
  517. axis = self._get_axis_number(axis or 0)
  518. dense_valid = self.to_dense().valid()
  519. if inplace:
  520. raise NotImplementedError("Cannot perform inplace dropna"
  521. " operations on a SparseSeries")
  522. if isnull(self.fill_value):
  523. return dense_valid
  524. else:
  525. dense_valid = dense_valid[dense_valid != self.fill_value]
  526. return dense_valid.to_sparse(fill_value=self.fill_value)
  527. @Appender(generic._shared_docs['shift'] % _shared_doc_kwargs)
  528. def shift(self, periods, freq=None, axis=0):
  529. if periods == 0:
  530. return self.copy()
  531. # no special handling of fill values yet
  532. if not isnull(self.fill_value):
  533. shifted = self.to_dense().shift(periods, freq=freq,
  534. axis=axis)
  535. return shifted.to_sparse(fill_value=self.fill_value,
  536. kind=self.kind)
  537. if freq is not None:
  538. return self._constructor(
  539. self.sp_values, sparse_index=self.sp_index,
  540. index=self.index.shift(periods, freq),
  541. fill_value=self.fill_value).__finalize__(self)
  542. int_index = self.sp_index.to_int_index()
  543. new_indices = int_index.indices + periods
  544. start, end = new_indices.searchsorted([0, int_index.length])
  545. new_indices = new_indices[start:end]
  546. new_sp_index = _make_index(len(self), new_indices, self.sp_index)
  547. arr = self.values._simple_new(self.sp_values[start:end].copy(),
  548. new_sp_index, fill_value=np.nan)
  549. return self._constructor(arr, index=self.index).__finalize__(self)
  550. def combine_first(self, other):
  551. """
  552. Combine Series values, choosing the calling Series's values
  553. first. Result index will be the union of the two indexes
  554. Parameters
  555. ----------
  556. other : Series
  557. Returns
  558. -------
  559. y : Series
  560. """
  561. if isinstance(other, SparseSeries):
  562. other = other.to_dense()
  563. dense_combined = self.to_dense().combine_first(other)
  564. return dense_combined.to_sparse(fill_value=self.fill_value)
  565. def to_coo(self, row_levels=(0, ), column_levels=(1, ), sort_labels=False):
  566. """
  567. Create a scipy.sparse.coo_matrix from a SparseSeries with MultiIndex.
  568. Use row_levels and column_levels to determine the row and column
  569. coordinates respectively. row_levels and column_levels are the names
  570. (labels) or numbers of the levels. {row_levels, column_levels} must be
  571. a partition of the MultiIndex level names (or numbers).
  572. .. versionadded:: 0.16.0
  573. Parameters
  574. ----------
  575. row_levels : tuple/list
  576. column_levels : tuple/list
  577. sort_labels : bool, default False
  578. Sort the row and column labels before forming the sparse matrix.
  579. Returns
  580. -------
  581. y : scipy.sparse.coo_matrix
  582. rows : list (row labels)
  583. columns : list (column labels)
  584. Examples
  585. --------
  586. >>> from numpy import nan
  587. >>> s = Series([3.0, nan, 1.0, 3.0, nan, nan])
  588. >>> s.index = MultiIndex.from_tuples([(1, 2, 'a', 0),
  589. (1, 2, 'a', 1),
  590. (1, 1, 'b', 0),
  591. (1, 1, 'b', 1),
  592. (2, 1, 'b', 0),
  593. (2, 1, 'b', 1)],
  594. names=['A', 'B', 'C', 'D'])
  595. >>> ss = s.to_sparse()
  596. >>> A, rows, columns = ss.to_coo(row_levels=['A', 'B'],
  597. column_levels=['C', 'D'],
  598. sort_labels=True)
  599. >>> A
  600. <3x4 sparse matrix of type '<class 'numpy.float64'>'
  601. with 3 stored elements in COOrdinate format>
  602. >>> A.todense()
  603. matrix([[ 0., 0., 1., 3.],
  604. [ 3., 0., 0., 0.],
  605. [ 0., 0., 0., 0.]])
  606. >>> rows
  607. [(1, 1), (1, 2), (2, 1)]
  608. >>> columns
  609. [('a', 0), ('a', 1), ('b', 0), ('b', 1)]
  610. """
  611. A, rows, columns = _sparse_series_to_coo(self, row_levels,
  612. column_levels,
  613. sort_labels=sort_labels)
  614. return A, rows, columns
  615. @classmethod
  616. def from_coo(cls, A, dense_index=False):
  617. """
  618. Create a SparseSeries from a scipy.sparse.coo_matrix.
  619. .. versionadded:: 0.16.0
  620. Parameters
  621. ----------
  622. A : scipy.sparse.coo_matrix
  623. dense_index : bool, default False
  624. If False (default), the SparseSeries index consists of only the
  625. coords of the non-null entries of the original coo_matrix.
  626. If True, the SparseSeries index consists of the full sorted
  627. (row, col) coordinates of the coo_matrix.
  628. Returns
  629. -------
  630. s : SparseSeries
  631. Examples
  632. ---------
  633. >>> from scipy import sparse
  634. >>> A = sparse.coo_matrix(([3.0, 1.0, 2.0], ([1, 0, 0], [0, 2, 3])),
  635. shape=(3, 4))
  636. >>> A
  637. <3x4 sparse matrix of type '<class 'numpy.float64'>'
  638. with 3 stored elements in COOrdinate format>
  639. >>> A.todense()
  640. matrix([[ 0., 0., 1., 2.],
  641. [ 3., 0., 0., 0.],
  642. [ 0., 0., 0., 0.]])
  643. >>> ss = SparseSeries.from_coo(A)
  644. >>> ss
  645. 0 2 1
  646. 3 2
  647. 1 0 3
  648. dtype: float64
  649. BlockIndex
  650. Block locations: array([0], dtype=int32)
  651. Block lengths: array([3], dtype=int32)
  652. """
  653. return _coo_to_sparse_series(A, dense_index=dense_index)
  654. # overwrite series methods with unaccelerated versions
  655. ops.add_special_arithmetic_methods(SparseSeries, use_numexpr=False,
  656. **ops.series_special_funcs)
  657. ops.add_flex_arithmetic_methods(SparseSeries, use_numexpr=False,
  658. **ops.series_flex_funcs)
  659. # overwrite basic arithmetic to use SparseSeries version
  660. # force methods to overwrite previous definitions.
  661. ops.add_special_arithmetic_methods(SparseSeries, _arith_method,
  662. comp_method=None,
  663. bool_method=None, use_numexpr=False,
  664. force=True)
  665. # backwards compatiblity
  666. class SparseTimeSeries(SparseSeries):
  667. def __init__(self, *args, **kwargs):
  668. # deprecation TimeSeries, #10890
  669. warnings.warn("SparseTimeSeries is deprecated. Please use "
  670. "SparseSeries", FutureWarning, stacklevel=2)
  671. super(SparseTimeSeries, self).__init__(*args, **kwargs)