Skip to content

Commit f6d48ca

Browse files
y-pwesm
y-p
authored andcommitted
BUG: hash random. in 3.3 exposed reliance on dict traversal order. #2331
1 parent d5a8166 commit f6d48ca

File tree

4 files changed

+17
-9
lines changed

4 files changed

+17
-9
lines changed

pandas/core/groupby.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pandas.core.series import Series
1111
from pandas.core.panel import Panel
1212
from pandas.util.decorators import cache_readonly, Appender
13+
from pandas.util.compat import OrderedDict
1314
import pandas.core.algorithms as algos
1415
import pandas.core.common as com
1516
import pandas.lib as lib
@@ -1525,15 +1526,15 @@ def aggregate(self, arg, *args, **kwargs):
15251526
if isinstance(arg, basestring):
15261527
return getattr(self, arg)(*args, **kwargs)
15271528

1528-
result = {}
1529+
result = OrderedDict()
15291530
if isinstance(arg, dict):
15301531
if self.axis != 0: # pragma: no cover
15311532
raise ValueError('Can only pass dict with axis=0')
15321533

15331534
obj = self._obj_with_exclusions
15341535

15351536
if any(isinstance(x, (list, tuple, dict)) for x in arg.values()):
1536-
new_arg = {}
1537+
new_arg = OrderedDict()
15371538
for k, v in arg.iteritems():
15381539
if not isinstance(v, (tuple, list, dict)):
15391540
new_arg[k] = [v]

pandas/tests/test_format.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,8 @@ def test_dict_entries(self):
793793
df = DataFrame({'A': [{'a':1, 'b':2}]})
794794

795795
val = df.to_string()
796-
self.assertTrue("{'a': 1, 'b': 2}" in val)
796+
self.assertTrue("'a': 1" in val)
797+
self.assertTrue("'b': 2" in val)
797798

798799
def test_to_latex(self):
799800
# it works!

pandas/tests/test_groupby.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,7 @@ def test_agg_multiple_functions_too_many_lambdas(self):
18591859

18601860
def test_more_flexible_frame_multi_function(self):
18611861
from pandas import concat
1862+
from pandas.util.compat import OrderedDict
18621863

18631864
grouped = self.df.groupby('A')
18641865

@@ -1868,8 +1869,8 @@ def test_more_flexible_frame_multi_function(self):
18681869
expected = concat([exmean, exstd], keys=['mean', 'std'], axis=1)
18691870
expected = expected.swaplevel(0, 1, axis=1).sortlevel(0, axis=1)
18701871

1871-
result = grouped.aggregate({'C' : [np.mean, np.std],
1872-
'D' : [np.mean, np.std]})
1872+
d=OrderedDict([['C',[np.mean, np.std]],['D',[np.mean, np.std]]])
1873+
result = grouped.aggregate(d)
18731874

18741875
assert_frame_equal(result, expected)
18751876

@@ -1884,10 +1885,12 @@ def test_more_flexible_frame_multi_function(self):
18841885
def foo(x): return np.mean(x)
18851886
def bar(x): return np.std(x, ddof=1)
18861887
result = grouped.aggregate({'C' : np.mean,
1887-
'D' : {'foo': np.mean,
1888-
'bar': np.std}})
1888+
'D' : OrderedDict([['foo', np.mean],
1889+
['bar', np.std]])})
1890+
18891891
expected = grouped.aggregate({'C' : [np.mean],
18901892
'D' : [foo, bar]})
1893+
18911894
assert_frame_equal(result, expected)
18921895

18931896
def test_multi_function_flexible_mix(self):
@@ -1896,7 +1899,7 @@ def test_multi_function_flexible_mix(self):
18961899
grouped = self.df.groupby('A')
18971900

18981901
result = grouped.aggregate({'C' : {'foo' : 'mean',
1899-
'bar' : 'std'},
1902+
'bar' : 'std'},
19001903
'D' : 'sum'})
19011904
result2 = grouped.aggregate({'C' : {'foo' : 'mean',
19021905
'bar' : 'std'},

pandas/tseries/frequencies.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,10 @@ def get_period_alias(offset_str):
339339
_offset_map[_name] = offsets.WeekOfMonth(week=_iweek, weekday=_i)
340340
_rule_aliases[_name.replace('-', '@')] = _name
341341

342-
_legacy_reverse_map = dict((v, k) for k, v in _rule_aliases.iteritems())
342+
# Note that _rule_aliases is not 1:1 (d[BA]==d[A@DEC]), and so traversal
343+
# order matters when constructing an inverse. we pick one. #2331
344+
_legacy_reverse_map = dict((v, k) for k, v in
345+
reversed(sorted(_rule_aliases.iteritems())))
343346

344347
# for helping out with pretty-printing and name-lookups
345348

0 commit comments

Comments
 (0)