@@ -1985,52 +1985,79 @@ def reindex(self, axes_to_reindex=None, new_axis=None, fill_value=nan, inplace=F
1985
1985
a0 c0 -1 -1
1986
1986
a1 c0 2 1
1987
1987
"""
1988
- if isinstance (axes_to_reindex , str ) and '=' in axes_to_reindex :
1989
- axes_to_reindex = Axis (axes_to_reindex )
1990
- elif isinstance (axes_to_reindex , Group ):
1991
- axes_to_reindex = Axis (axes_to_reindex )
1988
+ def labels_def_and_name_to_axis (labels_def , axis_name = None ):
1989
+ # TODO: the rename functionality seems weird to me.
1990
+ # I think we should either raise an error if the axis name
1991
+ # is different (force using new_axis=other_axis.labels instead
1992
+ # of new_axis=other_axis) OR do not do use the old name
1993
+ # (and make sure this effectively does a rename).
1994
+ # it might have been the unintended consequence of supporting a
1995
+ # list of labels as new_axis
1996
+ axis = labels_def if isinstance (labels_def , Axis ) else Axis (labels_def )
1997
+ return axis .rename (axis_name ) if axis_name is not None else axis
1998
+
1999
+ def axis_ref_to_axis (axes , axis_ref ):
2000
+ if isinstance (axis_ref , Axis ) or is_axis_ref (axis_ref ):
2001
+ return axes [axis_ref ]
2002
+ else :
2003
+ raise TypeError (
2004
+ "In Array.reindex, source axes must be Axis objects or axis references ('axis name', "
2005
+ "X.axis_name or axis_integer_position) but got object of "
2006
+ f"type { type (axis_ref ).__name__ } instead."
2007
+ )
2008
+
2009
+ def is_axis_ref (axis_ref ):
2010
+ return isinstance (axis_ref , (int , str , AxisReference ))
2011
+
2012
+ def is_axis_def (axis_def ):
2013
+ return ((isinstance (axis_def , str ) and '=' in axis_def )
2014
+ or isinstance (axis_def , Group ))
1992
2015
1993
- # XXX: can't we move this to AxisCollection.replace?
1994
2016
if new_axis is None :
1995
- if isinstance (axes_to_reindex , (int , str , AxisReference )):
2017
+ if isinstance (axes_to_reindex , Axis ) and not isinstance (axes_to_reindex , AxisReference ):
2018
+ axes_to_reindex = {axes_to_reindex : axes_to_reindex }
2019
+ elif is_axis_def (axes_to_reindex ):
2020
+ axis = Axis (axes_to_reindex )
2021
+ axes_to_reindex = {axis : axis }
2022
+ elif is_axis_ref (axes_to_reindex ):
1996
2023
raise TypeError ("In Array.reindex, when using an axis reference ('axis name', X.axis_name or "
1997
2024
"axis_integer_position) as axes_to_reindex, you must provide a value for `new_axis`." )
1998
- elif isinstance ( axes_to_reindex , Axis ):
1999
- new_axis = axes_to_reindex
2000
- axes_to_reindex = self . axes [ axes_to_reindex ]
2001
- else :
2002
- assert isinstance (axes_to_reindex , (tuple , list , dict , AxisCollection ))
2025
+ # otherwise axes_to_reindex should be None (when kwargs are used),
2026
+ # a dict or a sequence of axes
2027
+ # axes_to_reindex can be None when kwargs are used
2028
+ assert ( axes_to_reindex is None or
2029
+ isinstance (axes_to_reindex , (tuple , list , dict , AxisCollection ) ))
2003
2030
else :
2004
- if isinstance (axes_to_reindex , (int , str , Axis )):
2005
- axes_to_reindex = self .axes [axes_to_reindex ]
2006
- else :
2031
+ if not (isinstance (axes_to_reindex , Axis ) or is_axis_ref (axes_to_reindex )):
2007
2032
raise TypeError (
2008
- "In Array.reindex, when `new_axis` is used, `axes_to_reindex`"
2009
- " must be an Axis object or an axis reference ('axis name', "
2010
- "X.axis_name or axis_integer_position) but got object of "
2011
- f"type { type (axes_to_reindex ).__name__ } instead."
2033
+ "In Array.reindex, when `new_axis` is used, `axes_to_reindex` "
2034
+ "must be an Axis object or an axis reference ('axis name', "
2035
+ f "X.axis_name or axis_integer_position) but got { axes_to_reindex } "
2036
+ f"(which is of type { type (axes_to_reindex ).__name__ } ) instead."
2012
2037
)
2013
- assert isinstance (axes_to_reindex , Axis )
2014
- old_axis_name = axes_to_reindex .name
2015
-
2016
- if not isinstance (new_axis , Axis ):
2017
- new_axis = Axis (new_axis )
2018
- # TODO: this functionality seems weird to me.
2019
- # I think we should either raise an error if the axis name
2020
- # is different (force using new_axis=other_axis.labels instead
2021
- # of new_axis=other_axis) OR do not do use the old name
2022
- # (and make sure this effectively does a rename)
2023
- new_axis = new_axis .rename (old_axis_name )
2038
+ axes_to_reindex = {axes_to_reindex : new_axis }
2039
+ new_axis = None
2024
2040
2025
- if isinstance (axes_to_reindex , (list , tuple )) and all ([ isinstance ( axis , Axis ) for axis in axes_to_reindex ]) :
2041
+ if isinstance (axes_to_reindex , (list , tuple )):
2026
2042
axes_to_reindex = AxisCollection (axes_to_reindex )
2027
2043
2044
+ assert new_axis is None
2045
+ assert axes_to_reindex is None or isinstance (axes_to_reindex , (dict , AxisCollection ))
2046
+
2028
2047
if isinstance (axes_to_reindex , AxisCollection ):
2029
- assert new_axis is None
2030
- # add extra axes if needed
2048
+ # | axes_to_reindex is needed because axes_to_reindex can contain more axes than self.axes
2031
2049
res_axes = AxisCollection ([axes_to_reindex .get (axis , axis ) for axis in self .axes ]) | axes_to_reindex
2032
2050
else :
2033
- res_axes = self .axes .replace (axes_to_reindex , new_axis , ** kwargs )
2051
+ # TODO: move this to AxisCollection.replace
2052
+ if isinstance (axes_to_reindex , dict ):
2053
+ new_axes_to_reindex = {}
2054
+ for k , v in axes_to_reindex .items ():
2055
+ src_axis = axis_ref_to_axis (self .axes , k )
2056
+ dst_axis = labels_def_and_name_to_axis (v , src_axis .name )
2057
+ new_axes_to_reindex [src_axis ] = dst_axis
2058
+ axes_to_reindex = new_axes_to_reindex
2059
+
2060
+ res_axes = self .axes .replace (axes_to_reindex , ** kwargs )
2034
2061
res = full (res_axes , fill_value , dtype = common_dtype ((self .data , fill_value )))
2035
2062
2036
2063
def get_group (res_axes , self_axis ):
@@ -2039,9 +2066,9 @@ def get_group(res_axes, self_axis):
2039
2066
return self_axis [:]
2040
2067
else :
2041
2068
return self_axis [self_axis .intersection (res_axis ).labels ]
2042
- self_labels = tuple (get_group (res_axes , axis ) for axis in self .axes )
2043
- res_labels = tuple (res_axes [group .axis ][group ] for group in self_labels )
2044
- res [res_labels ] = self [self_labels ]
2069
+ self_groups = tuple (get_group (res_axes , axis ) for axis in self .axes )
2070
+ res_groups = tuple (res_axes [group .axis ][group ] for group in self_groups )
2071
+ res [res_groups ] = self [self_groups ]
2045
2072
if inplace :
2046
2073
self .axes = res .axes
2047
2074
self .data = res .data
0 commit comments