Skip to content

Commit 1308264

Browse files
committed
Merge commit 'v0.15.1-125-ge463818' into debian
* commit 'v0.15.1-125-ge463818': TST: Moved test functions to module level. pandas-dev#8023 TST: skip on < mpl 1.3.1 (GH8947) preserve left frame order in left merge BLD: run slow tests on new optional build 2.7_SLOW using current versions of everything BLD: run graphics tests on 2.7_LOCALE using old matplotlib BUG: Fixed font size (set it on both x and y axis). pandas-dev#8765 BUG: Resample across multiple days TST: 32-bit construction fix re GH8907 Categorical: let unique only return used categories BUG: fix doctests in pandas.core.common BUG: DatetimeIndex with time as key
2 parents 9447d6a + e463818 commit 1308264

18 files changed

+315
-150
lines changed

.travis.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ matrix:
3838
- BUILD_TYPE=conda
3939
- JOB_NAME: "27_nslow"
4040
- DOC_BUILD=true # if rst files were changed, build docs in parallel with tests
41+
- python: 2.7
42+
env:
43+
- NOSE_ARGS="slow and not network and not disabled"
44+
- FULL_DEPS=true
45+
- JOB_TAG=_SLOW
46+
- BUILD_TYPE=conda
47+
- JOB_NAME: "27_slow"
4148
- python: 3.3
4249
env:
4350
- NOSE_ARGS="not slow and not disabled"
@@ -76,6 +83,13 @@ matrix:
7683
- CLIPBOARD_GUI=qt4
7784
- BUILD_TYPE=pydata
7885
- JOB_NAME: "32_nslow"
86+
- python: 2.7
87+
env:
88+
- NOSE_ARGS="slow and not network and not disabled"
89+
- FULL_DEPS=true
90+
- JOB_TAG=_SLOW
91+
- BUILD_TYPE=conda
92+
- JOB_NAME: "27_slow"
7993
- python: 2.7
8094
env:
8195
- EXPERIMENTAL=true

ci/requirements-2.7_LOCALE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ xlrd=0.9.2
77
numpy=1.7.1
88
cython=0.19.1
99
bottleneck=0.8.0
10-
matplotlib=1.3.0
10+
matplotlib=1.2.1
1111
patsy=0.1.0
1212
sqlalchemy=0.8.1
1313
html5lib=1.0b2

ci/requirements-2.7_SLOW.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
dateutil
2+
pytz
3+
numpy
4+
cython
5+
matplotlib
6+
scipy
7+
patsy
8+
statsmodels
9+
xlwt
10+
openpyxl
11+
xlsxwriter
12+
xlrd
13+
numexpr
14+
pytables
15+
sqlalchemy
16+
lxml
17+
boto
18+
bottleneck
19+
psycopg2
20+
pymysql
21+
html5lib
22+
beautiful-soup
23+
httplib2
24+
python-gflags
25+
google-api-python-client

doc/source/whatsnew/v0.15.2.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ API changes
4242

4343
- Bug in concat of Series with ``category`` dtype which were coercing to ``object``. (:issue:`8641`)
4444

45+
- Bug in unique of Series with ``category`` dtype, which returned all categories regardless
46+
whether they were "used" or not (see :issue:`8559` for the discussion).
47+
4548
- ``Series.all`` and ``Series.any`` now support the ``level`` and ``skipna`` parameters. ``Series.all``, ``Series.any``, ``Index.all``, and ``Index.any`` no longer support the ``out`` and ``keepdims`` parameters, which existed for compatibility with ndarray. Various index types no longer support the ``all`` and ``any`` aggregation functions and will now raise ``TypeError``. (:issue:`8302`):
4649

4750
.. ipython:: python
@@ -97,7 +100,10 @@ Bug Fixes
97100
- ``sql_schema`` now generates dialect appropriate ``CREATE TABLE`` statements (:issue:`8697`)
98101
- ``slice`` string method now takes step into account (:issue:`8754`)
99102
- Bug in ``BlockManager`` where setting values with different type would break block integrity (:issue:`8850`)
103+
- Bug in ``DatetimeIndex`` when using ``time`` object as key (:issue:`8667`)
104+
- Bug in ``merge`` where ``how='left'`` and ``sort=False`` would not preserve left frame order (:issue:`7331`)
100105
- Fix negative step support for label-based slices (:issue:`8753`)
106+
- Fix: The font size was only set on x axis if vertical or the y axis if horizontal. (:issue:`8765`)
101107

102108
Old behavior:
103109

@@ -145,7 +151,8 @@ Bug Fixes
145151
- BUG: Option context applies on __enter__ (:issue:`8514`)
146152

147153

148-
154+
- Bug in resample that causes a ValueError when resampling across multiple days
155+
and the last offset is not calculated from the start of the range (:issue:`8683`)
149156

150157

151158
- Bug in `pd.infer_freq`/`DataFrame.inferred_freq` that prevented proper sub-daily frequency inference

pandas/core/categorical.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,13 +1326,18 @@ def unique(self):
13261326
"""
13271327
Return the unique values.
13281328
1329-
This includes all categories, even if one or more is unused.
1329+
Unused categories are NOT returned.
13301330
13311331
Returns
13321332
-------
13331333
unique values : array
13341334
"""
1335-
return np.asarray(self.categories)
1335+
unique_codes = np.unique(self.codes)
1336+
# for compatibility with normal unique, which has nan last
1337+
if unique_codes[0] == -1:
1338+
unique_codes[0:-1] = unique_codes[1:]
1339+
unique_codes[-1] = -1
1340+
return take_1d(self.categories.values, unique_codes)
13361341

13371342
def equals(self, other):
13381343
"""

pandas/core/common.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,13 @@ def array_equivalent(left, right, strict_nan=False):
404404
405405
Examples
406406
--------
407-
>>> array_equivalent(np.array([1, 2, nan]), np.array([1, 2, nan]))
407+
>>> array_equivalent(
408+
... np.array([1, 2, np.nan]),
409+
... np.array([1, 2, np.nan]))
408410
True
409-
>>> array_equivalent(np.array([1, nan, 2]), np.array([1, 2, nan]))
411+
>>> array_equivalent(
412+
... np.array([1, np.nan, 2]),
413+
... np.array([1, 2, np.nan]))
410414
False
411415
"""
412416

@@ -2171,8 +2175,8 @@ def iterpairs(seq):
21712175
21722176
Examples
21732177
--------
2174-
>>> iterpairs([1, 2, 3, 4])
2175-
[(1, 2), (2, 3), (3, 4)
2178+
>>> list(iterpairs([1, 2, 3, 4]))
2179+
[(1, 2), (2, 3), (3, 4)]
21762180
"""
21772181
# input may not be sliceable
21782182
seq_it = iter(seq)

pandas/index.pyx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,14 @@ cdef class DatetimeEngine(Int64Engine):
545545
val = _to_i8(val)
546546
return self._get_loc_duplicates(val)
547547
values = self._get_index_values()
548-
conv = _to_i8(val)
549-
loc = values.searchsorted(conv, side='left')
548+
549+
try:
550+
conv = _to_i8(val)
551+
loc = values.searchsorted(conv, side='left')
552+
except TypeError:
553+
self._date_check_type(val)
554+
raise KeyError(val)
555+
550556
if loc == len(values) or util.get_value_at(values, loc) != conv:
551557
raise KeyError(val)
552558
return loc

pandas/tests/test_categorical.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,11 +769,17 @@ def test_min_max(self):
769769
self.assertEqual(_max, 1)
770770

771771
def test_unique(self):
772-
cat = Categorical(["a","b","c","d"])
773-
exp = np.asarray(["a","b","c","d"])
772+
cat = Categorical(["a","b"])
773+
exp = np.asarray(["a","b"])
774774
res = cat.unique()
775775
self.assert_numpy_array_equal(res, exp)
776-
self.assertEqual(type(res), type(exp))
776+
cat = Categorical(["a","b","a","a"], categories=["a","b","c"])
777+
res = cat.unique()
778+
self.assert_numpy_array_equal(res, exp)
779+
cat = Categorical(["a","b","a", np.nan], categories=["a","b","c"])
780+
res = cat.unique()
781+
exp = np.asarray(["a","b", np.nan], dtype=object)
782+
self.assert_numpy_array_equal(res, exp)
777783

778784
def test_mode(self):
779785
s = Categorical([1,1,2,4,5,5,5], categories=[5,4,3,2,1], ordered=True)

pandas/tests/test_graphics.py

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ def setUp(self):
7777
else:
7878
self.bp_n_objects = 8
7979

80+
self.mpl_le_1_2_1 = str(mpl.__version__) <= LooseVersion('1.2.1')
81+
self.mpl_ge_1_3_1 = str(mpl.__version__) >= LooseVersion('1.3.1')
82+
8083
def tearDown(self):
8184
tm.close()
8285

@@ -443,7 +446,6 @@ def setUp(self):
443446
import matplotlib as mpl
444447
mpl.rcdefaults()
445448

446-
self.mpl_le_1_2_1 = str(mpl.__version__) <= LooseVersion('1.2.1')
447449
self.ts = tm.makeTimeSeries()
448450
self.ts.name = 'ts'
449451

@@ -818,12 +820,13 @@ def test_hist_kwargs(self):
818820
self._check_text_labels(ax.yaxis.get_label(), 'Degree')
819821
tm.close()
820822

821-
ax = self.ts.plot(kind='hist', orientation='horizontal')
822-
self._check_text_labels(ax.xaxis.get_label(), 'Degree')
823-
tm.close()
823+
if self.mpl_ge_1_3_1:
824+
ax = self.ts.plot(kind='hist', orientation='horizontal')
825+
self._check_text_labels(ax.xaxis.get_label(), 'Degree')
826+
tm.close()
824827

825-
ax = self.ts.plot(kind='hist', align='left', stacked=True)
826-
tm.close()
828+
ax = self.ts.plot(kind='hist', align='left', stacked=True)
829+
tm.close()
827830

828831
@slow
829832
def test_hist_kde_color(self):
@@ -961,9 +964,6 @@ def setUp(self):
961964
import matplotlib as mpl
962965
mpl.rcdefaults()
963966

964-
self.mpl_le_1_2_1 = str(mpl.__version__) <= LooseVersion('1.2.1')
965-
self.mpl_ge_1_3_1 = str(mpl.__version__) >= LooseVersion('1.3.1')
966-
967967
self.tdf = tm.makeTimeDataFrame()
968968
self.hexbin_df = DataFrame({"A": np.random.uniform(size=20),
969969
"B": np.random.uniform(size=20),
@@ -2141,31 +2141,33 @@ def test_hist_df_coord(self):
21412141
self._check_box_coord(axes[2].patches, expected_y=np.array([0, 0, 0, 0, 0]),
21422142
expected_h=np.array([6, 7, 8, 9, 10]))
21432143

2144-
# horizontal
2145-
ax = df.plot(kind='hist', bins=5, orientation='horizontal')
2146-
self._check_box_coord(ax.patches[:5], expected_x=np.array([0, 0, 0, 0, 0]),
2147-
expected_w=np.array([10, 9, 8, 7, 6]))
2148-
self._check_box_coord(ax.patches[5:10], expected_x=np.array([0, 0, 0, 0, 0]),
2149-
expected_w=np.array([8, 8, 8, 8, 8]))
2150-
self._check_box_coord(ax.patches[10:], expected_x=np.array([0, 0, 0, 0, 0]),
2151-
expected_w=np.array([6, 7, 8, 9, 10]))
2152-
2153-
ax = df.plot(kind='hist', bins=5, stacked=True, orientation='horizontal')
2154-
self._check_box_coord(ax.patches[:5], expected_x=np.array([0, 0, 0, 0, 0]),
2155-
expected_w=np.array([10, 9, 8, 7, 6]))
2156-
self._check_box_coord(ax.patches[5:10], expected_x=np.array([10, 9, 8, 7, 6]),
2157-
expected_w=np.array([8, 8, 8, 8, 8]))
2158-
self._check_box_coord(ax.patches[10:], expected_x=np.array([18, 17, 16, 15, 14]),
2159-
expected_w=np.array([6, 7, 8, 9, 10]))
2160-
2161-
axes = df.plot(kind='hist', bins=5, stacked=True,
2162-
subplots=True, orientation='horizontal')
2163-
self._check_box_coord(axes[0].patches, expected_x=np.array([0, 0, 0, 0, 0]),
2164-
expected_w=np.array([10, 9, 8, 7, 6]))
2165-
self._check_box_coord(axes[1].patches, expected_x=np.array([0, 0, 0, 0, 0]),
2166-
expected_w=np.array([8, 8, 8, 8, 8]))
2167-
self._check_box_coord(axes[2].patches, expected_x=np.array([0, 0, 0, 0, 0]),
2168-
expected_w=np.array([6, 7, 8, 9, 10]))
2144+
if self.mpl_ge_1_3_1:
2145+
2146+
# horizontal
2147+
ax = df.plot(kind='hist', bins=5, orientation='horizontal')
2148+
self._check_box_coord(ax.patches[:5], expected_x=np.array([0, 0, 0, 0, 0]),
2149+
expected_w=np.array([10, 9, 8, 7, 6]))
2150+
self._check_box_coord(ax.patches[5:10], expected_x=np.array([0, 0, 0, 0, 0]),
2151+
expected_w=np.array([8, 8, 8, 8, 8]))
2152+
self._check_box_coord(ax.patches[10:], expected_x=np.array([0, 0, 0, 0, 0]),
2153+
expected_w=np.array([6, 7, 8, 9, 10]))
2154+
2155+
ax = df.plot(kind='hist', bins=5, stacked=True, orientation='horizontal')
2156+
self._check_box_coord(ax.patches[:5], expected_x=np.array([0, 0, 0, 0, 0]),
2157+
expected_w=np.array([10, 9, 8, 7, 6]))
2158+
self._check_box_coord(ax.patches[5:10], expected_x=np.array([10, 9, 8, 7, 6]),
2159+
expected_w=np.array([8, 8, 8, 8, 8]))
2160+
self._check_box_coord(ax.patches[10:], expected_x=np.array([18, 17, 16, 15, 14]),
2161+
expected_w=np.array([6, 7, 8, 9, 10]))
2162+
2163+
axes = df.plot(kind='hist', bins=5, stacked=True,
2164+
subplots=True, orientation='horizontal')
2165+
self._check_box_coord(axes[0].patches, expected_x=np.array([0, 0, 0, 0, 0]),
2166+
expected_w=np.array([10, 9, 8, 7, 6]))
2167+
self._check_box_coord(axes[1].patches, expected_x=np.array([0, 0, 0, 0, 0]),
2168+
expected_w=np.array([8, 8, 8, 8, 8]))
2169+
self._check_box_coord(axes[2].patches, expected_x=np.array([0, 0, 0, 0, 0]),
2170+
expected_w=np.array([6, 7, 8, 9, 10]))
21692171

21702172
@slow
21712173
def test_hist_df_legacy(self):

pandas/tests/test_index.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,27 @@ def test_reindex_preserves_tz_if_target_is_empty_list_or_array(self):
18861886
self.assertEqual(str(index.reindex([])[0].tz), 'US/Eastern')
18871887
self.assertEqual(str(index.reindex(np.array([]))[0].tz), 'US/Eastern')
18881888

1889+
def test_time_loc(self): # GH8667
1890+
from datetime import time
1891+
from pandas.index import _SIZE_CUTOFF
1892+
1893+
ns = _SIZE_CUTOFF + np.array([-100, 100],dtype=np.int64)
1894+
key = time(15, 11, 30)
1895+
start = key.hour * 3600 + key.minute * 60 + key.second
1896+
step = 24 * 3600
1897+
1898+
for n in ns:
1899+
idx = pd.date_range('2014-11-26', periods=n, freq='S')
1900+
ts = pd.Series(np.random.randn(n), index=idx)
1901+
i = np.arange(start, n, step)
1902+
1903+
tm.assert_array_equal(ts.index.get_loc(key), i)
1904+
tm.assert_series_equal(ts[key], ts.iloc[i])
1905+
1906+
left, right = ts.copy(), ts.copy()
1907+
left[key] *= -10
1908+
right.iloc[i] *= -10
1909+
tm.assert_series_equal(left, right)
18891910

18901911
class TestPeriodIndex(Base, tm.TestCase):
18911912
_holder = PeriodIndex

pandas/tools/merge.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,10 @@ def _get_join_indexers(left_keys, right_keys, sort=False, how='inner'):
479479
left_group_key, right_group_key, max_groups = \
480480
_factorize_keys(left_group_key, right_group_key, sort=sort)
481481

482+
# preserve left frame order if how == 'left' and sort == False
483+
kwargs = {'sort':sort} if how == 'left' else {}
482484
join_func = _join_functions[how]
483-
return join_func(left_group_key, right_group_key, max_groups)
485+
return join_func(left_group_key, right_group_key, max_groups, **kwargs)
484486

485487

486488
class _OrderedMerge(_MergeOperation):

pandas/tools/plotting.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,13 +1051,15 @@ def _adorn_subplots(self):
10511051
xticklabels = [labels.get(x, '') for x in ax.get_xticks()]
10521052
ax.set_xticklabels(xticklabels)
10531053
self._apply_axis_properties(ax.xaxis, rot=self.rot,
1054-
fontsize=self.fontsize)
1054+
fontsize=self.fontsize)
1055+
self._apply_axis_properties(ax.yaxis, fontsize=self.fontsize)
10551056
elif self.orientation == 'horizontal':
10561057
if self._need_to_set_index:
10571058
yticklabels = [labels.get(y, '') for y in ax.get_yticks()]
10581059
ax.set_yticklabels(yticklabels)
10591060
self._apply_axis_properties(ax.yaxis, rot=self.rot,
1060-
fontsize=self.fontsize)
1061+
fontsize=self.fontsize)
1062+
self._apply_axis_properties(ax.xaxis, fontsize=self.fontsize)
10611063

10621064
def _apply_axis_properties(self, axis, rot=None, fontsize=None):
10631065
labels = axis.get_majorticklabels() + axis.get_minorticklabels()

pandas/tools/tests/test_merge.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,13 @@ def test_left_join_index_multi_match_multiindex(self):
10221022

10231023
tm.assert_frame_equal(result, expected)
10241024

1025+
# GH7331 - maintain left frame order in left merge
1026+
right.reset_index(inplace=True)
1027+
right.columns = left.columns[:3].tolist() + right.columns[-1:].tolist()
1028+
result = merge(left, right, how='left', on=left.columns[:-1].tolist())
1029+
expected.index = np.arange(len(expected))
1030+
tm.assert_frame_equal(result, expected)
1031+
10251032
def test_left_join_index_multi_match(self):
10261033
left = DataFrame([
10271034
['c', 0],
@@ -1059,6 +1066,11 @@ def test_left_join_index_multi_match(self):
10591066

10601067
tm.assert_frame_equal(result, expected)
10611068

1069+
# GH7331 - maintain left frame order in left merge
1070+
result = merge(left, right.reset_index(), how='left', on='tag')
1071+
expected.index = np.arange(len(expected))
1072+
tm.assert_frame_equal(result, expected)
1073+
10621074
def test_join_multi_dtypes(self):
10631075

10641076
# test with multi dtypes in the join index

0 commit comments

Comments
 (0)