Skip to content

Commit bc5a745

Browse files
committed
BUG: broke circular reference in Index engine, sped up MultiIndex.from_tuples, GH #219
1 parent 0518b54 commit bc5a745

File tree

6 files changed

+35
-9
lines changed

6 files changed

+35
-9
lines changed

RELEASE.rst

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pandas 0.5.1
5858
- Add fast `get_value` and `put_value` methods to DataFrame and
5959
micro-performance tweaks (GH #360)
6060
- Add `cov` instance methods to Series and DataFrame (GH #194, PR #362)
61+
- Add bar plot option to `DataFrame.plot` (PR #348)
6162
6263
**Improvements to existing features**
6364

pandas/core/frame.py

-2
Original file line numberDiff line numberDiff line change
@@ -2445,8 +2445,6 @@ def _join_on(self, other, on, how, lsuffix, rsuffix):
24452445
join_key = self[on[0]].values
24462446
else:
24472447
join_key = lib.fast_zip([self[k] for k in on])
2448-
join_key = common._asarray_tuplesafe(join_key,
2449-
dtype=np.object_)
24502448
elif isinstance(on, np.ndarray) and len(on) == len(self):
24512449
join_key = on
24522450
else:

pandas/core/index.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,10 @@ def indexMap(self):
101101

102102
@cache_readonly
103103
def _engine(self):
104+
import weakref
104105
# property, for now, slow to look up
105-
return _engines.DictIndexEngine(self.values, self._map_indices)
106+
return _engines.DictIndexEngine(weakref.ref(self),
107+
self._map_indices)
106108

107109
def _get_level_number(self, level):
108110
if not isinstance(level, int):
@@ -1009,7 +1011,14 @@ def from_tuples(cls, tuples, sortorder=None, names=None):
10091011
"""
10101012
if len(tuples) == 0:
10111013
raise Exception('Cannot infer number of levels from empty list')
1012-
arrays = zip(*tuples)
1014+
1015+
if isinstance(tuples, np.ndarray):
1016+
arrays = list(lib.tuples_to_object_array(tuples).T)
1017+
elif isinstance(tuples, list):
1018+
arrays = list(lib.to_object_array_tuples(tuples).T)
1019+
else:
1020+
arrays = zip(*tuples)
1021+
10131022
return MultiIndex.from_arrays(arrays, sortorder=sortorder,
10141023
names=names)
10151024

pandas/src/engines.pyx

+6-5
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ cdef class DictIndexEngine(IndexEngine):
1010
'''
1111

1212
cdef readonly:
13-
ndarray values
13+
object index_weakref
1414
dict mapping
1515
object mapfun
1616

1717
cdef:
1818
bint initialized, integrity
1919

20-
def __init__(self, ndarray values, object mapfun):
21-
self.values = values
20+
def __init__(self, index_weakref, object mapfun):
21+
self.index_weakref = index_weakref
2222
self.initialized = 0
2323
self.integrity = 0
2424
self.mapfun = mapfun
@@ -51,8 +51,9 @@ cdef class DictIndexEngine(IndexEngine):
5151
return self.integrity == 1
5252

5353
cdef initialize(self):
54-
self.mapping = self.mapfun(self.values)
55-
if len(self.mapping) == len(self.values):
54+
values = self.index_weakref().values
55+
self.mapping = self.mapfun(values)
56+
if len(self.mapping) == len(values):
5657
self.integrity = 1
5758
self.initialized = 1
5859

pandas/src/parsing.pyx

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ def to_object_array(list rows):
2727

2828
return result
2929

30+
def tuples_to_object_array(ndarray[object] tuples):
31+
cdef:
32+
Py_ssize_t i, j, n, k, tmp
33+
ndarray[object, ndim=2] result
34+
tuple tup
35+
36+
n = len(tuples)
37+
k = len(tuples[0])
38+
result = np.empty((n, k), dtype=object)
39+
for i in range(n):
40+
tup = tuples[i]
41+
for j in range(k):
42+
result[i, j] = tup[j]
43+
44+
return result
45+
3046
def to_object_array_tuples(list rows):
3147
cdef:
3248
Py_ssize_t i, j, n, k, tmp

pandas/src/sandbox.pyx

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ cdef class SeriesIterator:
1414
def foo(object o):
1515
cdef int64_t bar = o
1616
return bar
17+

0 commit comments

Comments
 (0)