""" Factory methods to create N-D panels """ import warnings from pandas.compat import zip import pandas.compat as compat def create_nd_panel_factory(klass_name, orders, slices, slicer, aliases=None, stat_axis=2, info_axis=0, ns=None): """ manufacture a n-d class: .. deprecated:: 0.19.0 The recommended way to represent these types of n-dimensional data are with the `xarray package `__. Pandas provides a `.to_xarray()` method to automate this conversion. Parameters ---------- klass_name : the klass name orders : the names of the axes in order (highest to lowest) slices : a dictionary that defines how the axes map to the slice axis slicer : the class representing a slice of this panel aliases : a dictionary defining aliases for various axes default = { major : major_axis, minor : minor_axis } stat_axis : the default statistic axis default = 2 info_axis : the info axis Returns ------- a class object representing this panel """ # if slicer is a name, get the object if isinstance(slicer, compat.string_types): import pandas try: slicer = getattr(pandas, slicer) except: raise Exception("cannot create this slicer [%s]" % slicer) # build the klass ns = {} if not ns else ns klass = type(klass_name, (slicer, ), ns) # setup the axes klass._setup_axes(axes=orders, info_axis=info_axis, stat_axis=stat_axis, aliases=aliases, slicers=slices) klass._constructor_sliced = slicer # define the methods #### def __init__(self, *args, **kwargs): # deprecation GH13564 warnings.warn("\n{klass} is deprecated and will be removed in a " "future version.\nThe recommended way to represent " "these types of n-dimensional data are with the\n" "`xarray package " "`__.\n" "Pandas provides a `.to_xarray()` method to help " "automate this conversion.\n".format( klass=self.__class__.__name__), FutureWarning, stacklevel=2) if not (kwargs.get('data') or len(args)): raise Exception("must supply at least a data argument to [%s]" % klass_name) if 'copy' not in kwargs: kwargs['copy'] = False if 'dtype' not in kwargs: kwargs['dtype'] = None self._init_data(*args, **kwargs) klass.__init__ = __init__ def _get_plane_axes_index(self, axis): """ return the sliced index for this object """ # TODO: axis_name is not used, remove? axis_name = self._get_axis_name(axis) # noqa index = self._AXIS_ORDERS.index(axis) planes = [] if index: planes.extend(self._AXIS_ORDERS[0:index]) if index != self._AXIS_LEN: planes.extend(self._AXIS_ORDERS[index + 1:]) return planes klass._get_plane_axes_index = _get_plane_axes_index def _combine(self, other, func, axis=0): if isinstance(other, klass): return self._combine_with_constructor(other, func) return super(klass, self)._combine(other, func, axis=axis) klass._combine = _combine def _combine_with_constructor(self, other, func): # combine labels to form new axes new_axes = [] for a in self._AXIS_ORDERS: new_axes.append(getattr(self, a).union(getattr(other, a))) # reindex: could check that everything's the same size, but forget it d = dict([(a, ax) for a, ax in zip(self._AXIS_ORDERS, new_axes)]) d['copy'] = False this = self.reindex(**d) other = other.reindex(**d) result_values = func(this.values, other.values) return self._constructor(result_values, **d) klass._combine_with_constructor = _combine_with_constructor # set as NonImplemented operations which we don't support for f in ['to_frame', 'to_excel', 'to_sparse', 'groupby', 'join', 'filter', 'dropna', 'shift']: def func(self, *args, **kwargs): raise NotImplementedError("this operation is not supported") setattr(klass, f, func) # add the aggregate operations klass._add_aggregate_operations() klass._add_numeric_operations() return klass