@@ -35,25 +35,26 @@ cdef class Reducer:
3535 self .chunksize = k
3636 self .increment = k * arr.dtype.itemsize
3737
38+
3839 self .f = f
3940 self .arr = arr
4041 self .typ = None
4142 self .labels = labels
42- self .dummy, index = self ._check_dummy(dummy)
43+ self .dummy, index = self ._check_dummy(dummy = dummy )
4344
44- if axis == 0 :
45- self .labels = index
46- self .index = labels
47- else :
48- self .labels = labels
49- self .index = index
45+ self .labels = labels
46+ self .index = index
5047
5148 def _check_dummy (self , dummy = None ):
5249 cdef object index
5350
5451 if dummy is None :
5552 dummy = np.empty(self .chunksize, dtype = self .arr.dtype)
5653 index = None
54+
55+ # our ref is stolen later since we are creating this array
56+ # in cython, so increment first
57+ Py_INCREF(dummy)
5758 else :
5859 if dummy.dtype != self .arr.dtype:
5960 raise ValueError (' Dummy array must be same dtype' )
@@ -76,39 +77,48 @@ cdef class Reducer:
7677 ndarray arr, result, chunk
7778 Py_ssize_t i, incr
7879 flatiter it
79- object res, tchunk, name, labels, index, typ
80+ object res, name, labels, index
81+ object cached_typ = None
8082
8183 arr = self .arr
8284 chunk = self .dummy
8385 dummy_buf = chunk.data
8486 chunk.data = arr.data
8587 labels = self .labels
8688 index = self .index
87- typ = self .typ
8889 incr = self .increment
8990
9091 try :
9192 for i in range (self .nresults):
92- # need to make sure that we pass an actual object to the function
93- # and not just an ndarray
94- if typ is not None :
95- try :
96- if labels is not None :
97- name = labels[i]
93+
94+ if labels is not None :
95+ name = util.get_value_at(labels, i)
96+ else :
97+ name = None
98+
99+ # create the cached type
100+ # each time just reassign the data
101+ if i == 0 :
102+
103+ if self .typ is not None :
98104
99105 # recreate with the index if supplied
100106 if index is not None :
101- tchunk = typ(chunk, index = index, name = name, fastpath = True )
107+
108+ cached_typ = self .typ(chunk, index = index, name = name)
109+
102110 else :
103- tchunk = typ(chunk, name = name)
104111
105- except :
106- tchunk = chunk
107- typ = None
108- else :
109- tchunk = chunk
112+ # use the passsed typ, sans index
113+ cached_typ = self .typ(chunk, name = name)
110114
111- res = self .f(tchunk)
115+ # use the cached_typ if possible
116+ if cached_typ is not None :
117+ cached_typ._data._block.values = chunk
118+ cached_typ.name = name
119+ res = self .f(cached_typ)
120+ else :
121+ res = self .f(chunk)
112122
113123 if hasattr (res,' values' ):
114124 res = res.values
0 commit comments