27
27
is_bool_dtype ,
28
28
is_object_dtype ,
29
29
is_datetimelike_v_numeric ,
30
+ is_complex_dtype ,
30
31
is_float_dtype , is_numeric_dtype ,
31
32
is_numeric_v_string_like , is_extension_type ,
32
33
is_list_like ,
46
47
find_common_type )
47
48
from pandas .core .dtypes .missing import (
48
49
isna , notna , array_equivalent ,
49
- na_value_for_dtype ,
50
50
_isna_compat ,
51
51
is_null_datelike_scalar )
52
52
import pandas .core .dtypes .concat as _concat
@@ -444,18 +444,14 @@ def make_a_block(nv, ref_loc):
444
444
except (AttributeError , NotImplementedError ):
445
445
pass
446
446
447
- if isinstance (self , SparseBlock ):
448
- block = self .make_block_same_class (values = nv ,
449
- placement = ref_loc ,
450
- fastpath = True )
451
- else :
452
- block = self .make_block (values = nv ,
453
- placement = ref_loc ,
454
- fastpath = True )
447
+ block = self .make_block (values = nv ,
448
+ placement = ref_loc ,
449
+ fastpath = True )
450
+
455
451
return block
456
452
457
453
# ndim == 1
458
- if self .ndim == 1 or isinstance ( self , SparseBlock ) :
454
+ if self .ndim == 1 :
459
455
if mask .any ():
460
456
nv = f (mask , new_values , None )
461
457
else :
@@ -1392,6 +1388,11 @@ def where(self, other, cond, align=True, raise_on_error=True,
1392
1388
if hasattr (other , 'reindex_axis' ):
1393
1389
other = other .values
1394
1390
1391
+ if is_scalar (other ) or is_list_like (other ):
1392
+ fill_value = other
1393
+ else :
1394
+ fill_value = None
1395
+
1395
1396
if hasattr (cond , 'reindex_axis' ):
1396
1397
cond = cond .values
1397
1398
@@ -1405,7 +1406,8 @@ def where(self, other, cond, align=True, raise_on_error=True,
1405
1406
raise ValueError ("where must have a condition that is ndarray "
1406
1407
"like" )
1407
1408
else :
1408
- cond = cond .reshape (values .shape )
1409
+ if values .ndim == 1 :
1410
+ cond = cond .flatten ()
1409
1411
1410
1412
# our where function
1411
1413
def func (cond , values , other ):
@@ -1443,7 +1445,8 @@ def func(cond, values, other):
1443
1445
transpose = transpose )
1444
1446
return self ._maybe_downcast (blocks , 'infer' )
1445
1447
1446
- if self ._can_hold_na or self .ndim == 1 :
1448
+ if self ._can_hold_element (fill_value ) or \
1449
+ self .is_sparse or self .ndim == 1 :
1447
1450
1448
1451
if transpose :
1449
1452
result = result .T
@@ -1452,13 +1455,12 @@ def func(cond, values, other):
1452
1455
if try_cast :
1453
1456
result = self ._try_cast_result (result )
1454
1457
1455
- if isinstance (self , SparseBlock ):
1456
- fill_value = na_value_for_dtype (result .dtype )
1457
- return self .make_block_same_class (result ,
1458
- self .mgr_locs ,
1459
- fill_value = fill_value )
1458
+ if isinstance (result , np .ndarray ):
1459
+ ndim = result .ndim
1460
1460
else :
1461
- return self .make_block (result )
1461
+ ndim = None
1462
+
1463
+ return self .make_block (result , ndim = ndim , fill_value = fill_value )
1462
1464
1463
1465
# might need to separate out blocks
1464
1466
axis = cond .ndim - 1
@@ -1582,9 +1584,6 @@ def _nanpercentile(values, q, axis, **kw):
1582
1584
if is_scalar (result ):
1583
1585
return ax , self .make_block_scalar (result )
1584
1586
1585
- if isinstance (self , SparseBlock ):
1586
- result = SparseArray (result .flatten ())
1587
-
1588
1587
return ax , make_block (result ,
1589
1588
placement = np .arange (len (result )),
1590
1589
ndim = ndim )
@@ -1736,6 +1735,7 @@ class FloatBlock(FloatOrComplexBlock):
1736
1735
is_float = True
1737
1736
_downcast_dtype = 'int64'
1738
1737
1738
+ @classmethod
1739
1739
def _can_hold_element (self , element ):
1740
1740
if is_list_like (element ):
1741
1741
element = np .asarray (element )
@@ -1786,6 +1786,7 @@ class ComplexBlock(FloatOrComplexBlock):
1786
1786
__slots__ = ()
1787
1787
is_complex = True
1788
1788
1789
+ @classmethod
1789
1790
def _can_hold_element (self , element ):
1790
1791
if is_list_like (element ):
1791
1792
element = np .array (element )
@@ -1948,6 +1949,7 @@ class BoolBlock(NumericBlock):
1948
1949
is_bool = True
1949
1950
_can_hold_na = False
1950
1951
1952
+ @classmethod
1951
1953
def _can_hold_element (self , element ):
1952
1954
if is_list_like (element ):
1953
1955
element = np .asarray (element )
@@ -2632,10 +2634,62 @@ class SparseBlock(NonConsolidatableMixIn, Block):
2632
2634
is_sparse = True
2633
2635
is_numeric = True
2634
2636
_box_to_block_values = False
2635
- _can_hold_na = True
2636
2637
_ftype = 'sparse'
2637
2638
_holder = SparseArray
2638
2639
2640
+ def __init__ (self , values , placement , ndim = None , fastpath = False , ** kwargs ):
2641
+ super (SparseBlock , self ).__init__ (values , placement ,
2642
+ ndim , fastpath ,
2643
+ ** kwargs )
2644
+
2645
+ dtype = self .values .sp_values .dtype
2646
+
2647
+ if is_float_dtype (dtype ):
2648
+ self .is_float = True
2649
+ self ._can_hold_na = True
2650
+ elif is_complex_dtype (dtype ):
2651
+ self .is_complex = True
2652
+ self ._can_hold_na = True
2653
+ elif is_integer_dtype (dtype ):
2654
+ self .is_integer = True
2655
+ self ._can_hold_na = False
2656
+ elif is_bool_dtype (dtype ):
2657
+ self .is_bool = True
2658
+ self ._can_hold_na = False
2659
+ elif is_object_dtype (dtype ):
2660
+ self .is_object = True
2661
+ self ._can_hold_na = True
2662
+ else :
2663
+ self ._can_hold_na = False
2664
+
2665
+ def _can_hold_element (self , element ):
2666
+ """ require the same dtype as ourselves """
2667
+ dtype = self .values .sp_values .dtype
2668
+
2669
+ if is_bool_dtype (dtype ):
2670
+ return BoolBlock ._can_hold_element (element )
2671
+ elif is_integer_dtype (dtype ):
2672
+ if is_list_like (element ):
2673
+ element = np .array (element )
2674
+ tipo = element .dtype .type
2675
+ return (issubclass (tipo , np .integer ) and
2676
+ not issubclass (tipo ,
2677
+ (np .datetime64 ,
2678
+ np .timedelta64 )) and
2679
+ dtype .itemsize >= element .dtype .itemsize )
2680
+ return is_integer (element )
2681
+ elif is_float_dtype (dtype ):
2682
+ return FloatBlock ._can_hold_element (element )
2683
+ elif is_complex_dtype (dtype ):
2684
+ return ComplexBlock ._can_hold_element (element )
2685
+ elif is_object_dtype (dtype ):
2686
+ return True
2687
+ else :
2688
+ return False
2689
+
2690
+ def coerce_to_target_dtype (self , other , copy = True ):
2691
+ return super (SparseBlock , self ).coerce_to_target_dtype (other , copy )
2692
+
2639
2693
@property
2640
2694
def shape (self ):
2641
2695
return (len (self .mgr_locs ), self .sp_index .length )
@@ -2696,6 +2750,20 @@ def copy(self, deep=True, mgr=None):
2696
2750
kind = self .kind , copy = deep ,
2697
2751
placement = self .mgr_locs )
2698
2752
2753
+ def make_block (self , values , placement = None ,
2754
+ ndim = None , fill_value = None , ** kwargs ):
2755
+ """
2756
+ Create a new block, with type inference propagate any values that are
2757
+ not specified
2758
+ """
2759
+ if fill_value is not None and isinstance (values , SparseArray ):
2760
+ values = SparseArray (values .to_dense (), fill_value = fill_value ,
2761
+ kind = values .kind , dtype = values .dtype )
2762
+
2763
+ return super (SparseBlock , self ).make_block (values , placement = placement ,
2764
+ ndim = ndim , fill_value = None ,
2765
+ ** kwargs )
2766
+
2699
2767
def make_block_same_class (self , values , placement , sparse_index = None ,
2700
2768
kind = None , dtype = None , fill_value = None ,
2701
2769
copy = False , fastpath = True , ** kwargs ):
@@ -2726,7 +2794,7 @@ def make_block_same_class(self, values, placement, sparse_index=None,
2726
2794
2727
2795
new_values = SparseArray (values , sparse_index = sparse_index ,
2728
2796
kind = kind or self .kind , dtype = dtype ,
2729
- fill_value = fill_value , copy = copy )
2797
+ fill_value = fill_value , copy = copy ). flatten ()
2730
2798
return self .make_block (new_values , fastpath = fastpath ,
2731
2799
placement = placement )
2732
2800
@@ -2792,9 +2860,15 @@ def sparse_reindex(self, new_index):
2792
2860
return self .make_block_same_class (values , sparse_index = new_index ,
2793
2861
placement = self .mgr_locs )
2794
2862
2863
+ def _try_coerce_result (self , result ):
2864
+ """ reverse of try_coerce_args """
2865
+ if isinstance (result , np .ndarray ):
2866
+ result = SparseArray (result .flatten (), kind = self .kind )
2867
+ return result
2868
+
2795
2869
2796
2870
def make_block (values , placement , klass = None , ndim = None , dtype = None ,
2797
- fastpath = False ):
2871
+ fastpath = False , ** kwargs ):
2798
2872
if klass is None :
2799
2873
dtype = dtype or values .dtype
2800
2874
vtype = dtype .type
0 commit comments