-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
/
Copy pathpanelnd.py
109 lines (85 loc) · 3.59 KB
/
panelnd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
""" Factory methods to create N-D panels """
import pandas.lib as lib
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:
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):
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 """
axis_name = self._get_axis_name(axis)
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) + 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("%s is not implemented" % f)
setattr(klass, f, func)
# add the aggregate operations
klass._add_aggregate_operations()
klass._add_numeric_operations()
return klass