@@ -30,33 +30,6 @@ def merge(left, right, how='inner', on=None, left_on=None, right_on=None,
30
30
if __debug__ : merge .__doc__ = _merge_doc % '\n left : DataFrame'
31
31
32
32
33
- def concat (objs , axis = 0 , join = 'outer' , join_axes = None ,
34
- ignore_index = False , verify_integrity = False ):
35
- """
36
- Concatenate DataFrame objects row or column wise
37
-
38
- Parameters
39
- ----------
40
- objs : list of DataFrame objects
41
- axis : {0, 1}, default 0
42
- The axis to concatenate along
43
- join : {'inner', 'outer'}, default 'outer'
44
- How to handle indexes on other axis(es)
45
- join_index : index-like
46
- verify_integrity : boolean, default False
47
- Check whether the new concatenated axis contains duplicates. This can
48
- be very expensive relative to the actual data concatenation
49
-
50
- Returns
51
- -------
52
- concatenated : DataFrame
53
- """
54
- op = Concatenator (objs , axis = axis , join_axes = join_axes ,
55
- ignore_index = ignore_index , join = join ,
56
- verify_integrity = verify_integrity )
57
- return op .get_result ()
58
-
59
-
60
33
61
34
# TODO: NA group handling
62
35
# TODO: transformations??
@@ -614,14 +587,42 @@ def _get_all_block_kinds(blockmaps):
614
587
#----------------------------------------------------------------------
615
588
# Concatenate DataFrame objects
616
589
590
+ def concat (objs , axis = 0 , join = 'outer' , join_axes = None , ignore_index = False ,
591
+ keys = None , names = None , levels = None , verify_integrity = False ):
592
+ """
593
+ Concatenate DataFrame objects row or column wise
594
+
595
+ Parameters
596
+ ----------
597
+ objs : list of DataFrame objects
598
+ axis : {0, 1}, default 0
599
+ The axis to concatenate along
600
+ join : {'inner', 'outer'}, default 'outer'
601
+ How to handle indexes on other axis(es)
602
+ join_index : index-like
603
+ verify_integrity : boolean, default False
604
+ Check whether the new concatenated axis contains duplicates. This can
605
+ be very expensive relative to the actual data concatenation
606
+
607
+ Returns
608
+ -------
609
+ concatenated : DataFrame
610
+ """
611
+ op = _Concatenator (objs , axis = axis , join_axes = join_axes ,
612
+ ignore_index = ignore_index , join = join ,
613
+ keys = keys , levels = levels , names = names ,
614
+ verify_integrity = verify_integrity )
615
+ return op .get_result ()
616
+
617
617
618
- class Concatenator (object ):
618
+ class _Concatenator (object ):
619
619
"""
620
620
Orchestrates a concatenation operation for BlockManagers, with little hacks
621
621
to support sparse data structures, etc.
622
622
"""
623
623
624
624
def __init__ (self , objs , axis = 0 , join = 'outer' , join_axes = None ,
625
+ keys = None , levels = None , names = None ,
625
626
ignore_index = False , verify_integrity = False ):
626
627
if join == 'outer' :
627
628
self .intersect = False
@@ -645,6 +646,10 @@ def __init__(self, objs, axis=0, join='outer', join_axes=None,
645
646
646
647
self .join_axes = join_axes
647
648
649
+ self .keys = keys
650
+ self .names = names
651
+ self .levels = levels
652
+
648
653
self .ignore_index = ignore_index
649
654
self .verify_integrity = verify_integrity
650
655
@@ -763,9 +768,7 @@ def _get_new_axes(self):
763
768
if self .ignore_index :
764
769
concat_axis = None
765
770
else :
766
- concat_axis = _concat_indexes ([x ._data .axes [self .axis ]
767
- for x in self .objs ])
768
- self ._maybe_check_integrity (concat_axis )
771
+ concat_axis = self ._get_concat_axis ()
769
772
770
773
new_axes [self .axis ] = concat_axis
771
774
@@ -790,6 +793,19 @@ def _get_new_axes(self):
790
793
791
794
return new_axes
792
795
796
+ def _get_concat_axis (self ):
797
+ indexes = [x ._data .axes [self .axis ] for x in self .objs ]
798
+
799
+ if self .keys is None :
800
+ concat_axis = _concat_indexes (indexes )
801
+ else :
802
+ concat_axis = _make_concat_multiindex (indexes , self .keys ,
803
+ self .levels , self .names )
804
+
805
+ self ._maybe_check_integrity (concat_axis )
806
+
807
+ return concat_axis
808
+
793
809
def _maybe_check_integrity (self , concat_index ):
794
810
if self .verify_integrity :
795
811
if not concat_index ._verify_integrity ():
@@ -798,10 +814,7 @@ def _maybe_check_integrity(self, concat_index):
798
814
% str (overlap ))
799
815
800
816
801
- def _concat_frames_hierarchical (frames , keys , groupings , axis = 0 ):
802
- names = [ping .name for ping in groupings ]
803
- levels = [ping .group_index for ping in groupings ]
804
-
817
+ def _concat_frames_hierarchical (frames , keys , names , levels , axis = 0 ):
805
818
if axis == 0 :
806
819
indexes = [x .index for x in frames ]
807
820
new_index = _make_concat_multiindex (indexes , keys , levels , names )
@@ -852,12 +865,7 @@ def _make_concat_multiindex(indexes, keys, levels, names):
852
865
else :
853
866
label_list .append (concat_index .values )
854
867
855
- consensus_name = indexes [0 ].names
856
- for index in indexes [1 :]:
857
- if index .names != consensus_name :
858
- consensus_name = [None ] * index .nlevels
859
- break
860
- names .extend (consensus_name )
868
+ names .extend (_get_consensus_names (indexes ))
861
869
862
870
return MultiIndex .from_arrays (label_list , names = names )
863
871
@@ -887,6 +895,14 @@ def _make_concat_multiindex(indexes, keys, levels, names):
887
895
labels .append (np .tile (np .arange (n ), len (indexes )))
888
896
return MultiIndex (levels = new_levels , labels = labels , names = names )
889
897
898
+ def _get_consensus_names (indexes ):
899
+ consensus_name = indexes [0 ].names
900
+ for index in indexes [1 :]:
901
+ if index .names != consensus_name :
902
+ consensus_name = [None ] * index .nlevels
903
+ break
904
+ return consensus_name
905
+
890
906
def _all_indexes_same (indexes ):
891
907
first = indexes [0 ]
892
908
for index in indexes [1 :]:
0 commit comments