Skip to content

Commit 6a14733

Browse files
committed
Merge tag 'v0.9.1' into debian
Version 0.9.1 * tag 'v0.9.1': RLS: Version 0.9.1 final BUG: icol() should propegate fill_value for sparse data frames pandas-dev#2249 TST: icol() should propegate fill_value for sparse data frames BUG: override SparseDataFrame.icol to use __getitem__ instead of accessing _data internals. close pandas-dev#2251 BUG: make Series.tz_localize work with length-0 non-DatetimeIndex. close pandas-dev#2248 BUG: parallel_coordinates bugfix with matplotlib 1.2.0. close pandas-dev#2237 BUG: issue constructing DataFrame from empty Series with name. close pandas-dev#2234 ENH: disable repr dependence on terminal width when running non-interactively. pandas-dev#1610 BUG: ExcelWriter raises exception on PeriodIndex pandas-dev#2240 BUG: SparseDataFrame.icol return SparseSeries. SparseSeries.from_array return SparseSeries. close pandas-dev#2227, pandas-dev#2229 BUG: fix tz-aware resampling issue. close pandas-dev#2245
2 parents 2266a9e + 9867f8a commit 6a14733

File tree

15 files changed

+174
-19
lines changed

15 files changed

+174
-19
lines changed

RELEASE.rst

+9-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Where to get it
2525
pandas 0.9.1
2626
============
2727

28-
**Release date:** NOT YET RELEASED
28+
**Release date:** 2012-11-14
2929

3030
**New features**
3131

@@ -103,6 +103,14 @@ pandas 0.9.1
103103
- Fix conversion of mixed-type DataFrame to ndarray with dup columns (#2236)
104104
- Fix duplicate columns issue (#2218, #2219)
105105
- Fix SparseSeries.__pow__ issue with NA input (#2220)
106+
- Fix icol with integer sequence failure (#2228)
107+
- Fixed resampling tz-aware time series issue (#2245)
108+
- SparseDataFrame.icol was not returning SparseSeries (#2227, #2229)
109+
- Enable ExcelWriter to handle PeriodIndex (#2240)
110+
- Fix issue constructing DataFrame from empty Series with name (#2234)
111+
- Use console-width detection in interactive sessions only (#1610)
112+
- Fix parallel_coordinates legend bug with mpl 1.2.0 (#2237)
113+
- Make tz_localize work in corner case of empty Series (#2248)
106114
107115
pandas 0.9.0
108116
============

doc/source/v0.9.1.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.. _whatsnew_0901:
22

3-
v0.9.1 (November 8, 2012)
4-
-------------------------
3+
v0.9.1 (November 14, 2012)
4+
--------------------------
55

66
This is a bugfix release from 0.9.0 and includes several new features and
77
enhancements along with a large number of bug fixes. The new features include

pandas/core/common.py

+8
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,14 @@ def _concat_compat(to_concat, axis=0):
10731073
else:
10741074
return np.concatenate(to_concat, axis=axis)
10751075

1076+
def in_interactive_session():
1077+
""" check if we're running in an interactive shell
1078+
1079+
returns True if running under python/ipython interactive shell
1080+
"""
1081+
import __main__ as main
1082+
return not hasattr(main, '__file__')
1083+
10761084
# Unicode consolidation
10771085
# ---------------------
10781086
#

pandas/core/frame.py

+24-10
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ class DataFrame(NDFrame):
321321
_auto_consolidate = True
322322
_verbose_info = True
323323
_het_axis = 1
324+
_col_klass = Series
324325

325326
_AXIS_NUMBERS = {
326327
'index': 0,
@@ -581,13 +582,15 @@ def _need_info_repr_(self):
581582
else:
582583
# save us
583584
if (len(self.index) > max_rows or
584-
len(self.columns) > terminal_width // 2):
585+
(com.in_interactive_session() and
586+
len(self.columns) > terminal_width // 2)):
585587
return True
586588
else:
587589
buf = StringIO()
588590
self.to_string(buf=buf)
589591
value = buf.getvalue()
590-
if max([len(l) for l in value.split('\n')]) > terminal_width:
592+
if (max([len(l) for l in value.split('\n')]) > terminal_width and
593+
com.in_interactive_session()):
591594
return True
592595
else:
593596
return False
@@ -1179,8 +1182,12 @@ def _helper_csvexcel(self, writer, na_rep=None, cols=None,
11791182
encoded_cols = list(cols)
11801183
writer.writerow(encoded_cols)
11811184

1182-
nlevels = getattr(self.index, 'nlevels', 1)
1183-
for j, idx in enumerate(self.index):
1185+
data_index = self.index
1186+
if isinstance(self.index, PeriodIndex):
1187+
data_index = self.index.to_timestamp()
1188+
1189+
nlevels = getattr(data_index, 'nlevels', 1)
1190+
for j, idx in enumerate(data_index):
11841191
row_fields = []
11851192
if index:
11861193
if nlevels == 1:
@@ -1733,7 +1740,15 @@ def icol(self, i):
17331740
return self.ix[:, i]
17341741

17351742
values = self._data.iget(i)
1736-
return Series.from_array(values, index=self.index, name=label)
1743+
if hasattr(self,'default_fill_value'):
1744+
s = self._col_klass.from_array(values, index=self.index,
1745+
name=label,
1746+
fill_value= self.default_fill_value)
1747+
else:
1748+
s = self._col_klass.from_array(values, index=self.index,
1749+
name=label)
1750+
1751+
return s
17371752

17381753
def _ixs(self, i, axis=0):
17391754
if axis == 0:
@@ -5083,6 +5098,9 @@ def extract_index(data):
50835098

50845099
def _prep_ndarray(values, copy=True):
50855100
if not isinstance(values, np.ndarray):
5101+
if len(values) == 0:
5102+
return np.empty((0, 0), dtype=object)
5103+
50865104
arr = np.asarray(values)
50875105
# NumPy strings are a pain, convert to object
50885106
if issubclass(arr.dtype.type, basestring):
@@ -5095,11 +5113,7 @@ def _prep_ndarray(values, copy=True):
50955113
values = values.copy()
50965114

50975115
if values.ndim == 1:
5098-
N = values.shape[0]
5099-
if N == 0:
5100-
values = values.reshape((values.shape[0], 0))
5101-
else:
5102-
values = values.reshape((values.shape[0], 1))
5116+
values = values.reshape((values.shape[0], 1))
51035117
elif values.ndim != 2:
51045118
raise Exception('Must pass 2-d input')
51055119

pandas/core/series.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -2756,7 +2756,15 @@ def tz_localize(self, tz, copy=True):
27562756
-------
27572757
localized : TimeSeries
27582758
"""
2759-
new_index = self.index.tz_localize(tz)
2759+
from pandas.tseries.index import DatetimeIndex
2760+
2761+
if not isinstance(self.index, DatetimeIndex):
2762+
if len(self.index) > 0:
2763+
raise Exception('Cannot tz-localize non-time series')
2764+
2765+
new_index = DatetimeIndex([], tz=tz)
2766+
else:
2767+
new_index = self.index.tz_localize(tz)
27602768

27612769
new_values = self.values
27622770
if copy:

pandas/sparse/frame.py

+32
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class SparseDataFrame(DataFrame):
6464
_columns = None
6565
_series = None
6666
_is_mixed_type = False
67+
_col_klass = SparseSeries
6768
ndim = 2
6869

6970
def __init__(self, data=None, index=None, columns=None,
@@ -342,6 +343,37 @@ def __getitem__(self, key):
342343
else: # pragma: no cover
343344
raise
344345

346+
def icol(self, i):
347+
"""
348+
Retrieve the i-th column or columns of the DataFrame by location
349+
350+
Parameters
351+
----------
352+
i : int, slice, or sequence of integers
353+
354+
Notes
355+
-----
356+
If slice passed, the resulting data will be a view
357+
358+
Returns
359+
-------
360+
column : Series (int) or DataFrame (slice, sequence)
361+
"""
362+
if isinstance(i, slice):
363+
# need to return view
364+
lab_slice = slice(label[0], label[-1])
365+
return self.ix[:, lab_slice]
366+
else:
367+
label = self.columns[i]
368+
if isinstance(label, Index):
369+
if self.columns.inferred_type == 'integer':
370+
# XXX re: #2228
371+
return self.reindex(columns=label)
372+
else:
373+
return self.ix[:, i]
374+
375+
return self[label]
376+
345377
@Appender(DataFrame.get_value.__doc__, indents=0)
346378
def get_value(self, index, col):
347379
s = self._series[col]

pandas/sparse/series.py

+7
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ def __new__(cls, data, index=None, sparse_index=None, kind='block',
146146
output.name = name
147147
return output
148148

149+
@classmethod
150+
def from_array(cls, arr, index=None, name=None, copy=False,fill_value=None):
151+
"""
152+
Simplified alternate constructor
153+
"""
154+
return SparseSeries(arr, index=index, name=name, copy=copy,fill_value=fill_value)
155+
149156
def __init__(self, data, index=None, sparse_index=None, kind='block',
150157
fill_value=None, name=None, copy=False):
151158
"""Data structure for labeled, sparse floating point data

pandas/sparse/tests/test_sparse.py

+12
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,18 @@ def test_getitem(self):
901901

902902
self.assertRaises(Exception, sdf.__getitem__, ['a', 'd'])
903903

904+
def test_icol(self):
905+
# #2227
906+
result = self.frame.icol(0)
907+
self.assertTrue(isinstance(result, SparseSeries))
908+
assert_sp_series_equal(result, self.frame['A'])
909+
910+
# preserve sparse index type. #2251
911+
data = {'A' : [0,1 ]}
912+
iframe = SparseDataFrame(data, default_kind='integer')
913+
self.assertEquals(type(iframe['A'].sp_index),
914+
type(iframe.icol(0).sp_index))
915+
904916
def test_set_value(self):
905917
res = self.frame.set_value('foobar', 'B', 1.5)
906918
self.assert_(res is not self.frame)

pandas/tests/test_frame.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,11 @@ def test_irow_icol_duplicates(self):
13271327
xp = df.ix[:, [0]]
13281328
assert_frame_equal(rs, xp)
13291329

1330+
def test_icol_sparse_propegate_fill_value(self):
1331+
from pandas.sparse.api import SparseDataFrame
1332+
df=SparseDataFrame({'A' : [999,1]},default_fill_value=999)
1333+
self.assertTrue( len(df['A'].sp_values) == len(df.icol(0).sp_values))
1334+
13301335
def test_iget_value(self):
13311336
for i, row in enumerate(self.frame.index):
13321337
for j, col in enumerate(self.frame.columns):
@@ -2269,11 +2274,16 @@ def test_constructor_orient(self):
22692274
assert_frame_equal(recons, expected)
22702275

22712276
def test_constructor_Series_named(self):
2272-
a = Series([1,2,3], index=['a','b','c'], name='x')
2277+
a = Series([1, 2, 3], index=['a', 'b', 'c'], name='x')
22732278
df = DataFrame(a)
22742279
self.assert_(df.columns[0] == 'x')
22752280
self.assert_(df.index.equals(a.index))
22762281

2282+
# #2234
2283+
a = Series([], name='x')
2284+
df = DataFrame(a)
2285+
self.assert_(df.columns[0] == 'x')
2286+
22772287
def test_constructor_Series_differently_indexed(self):
22782288
# name
22792289
s1 = Series([1, 2, 3], index=['a','b','c'], name='x')
@@ -3842,6 +3852,24 @@ def test_to_excel_from_excel(self):
38423852
assert_frame_equal(frame, recons)
38433853
os.remove(path)
38443854

3855+
def test_to_excel_periodindex(self):
3856+
try:
3857+
import xlwt
3858+
import xlrd
3859+
import openpyxl
3860+
except ImportError:
3861+
raise nose.SkipTest
3862+
3863+
for ext in ['xls', 'xlsx']:
3864+
path = '__tmp__.' + ext
3865+
frame = self.tsframe
3866+
xp = frame.resample('M', kind='period')
3867+
xp.to_excel(path, 'sht1')
3868+
3869+
reader = ExcelFile(path)
3870+
rs = reader.parse('sht1', index_col=0, parse_dates=True)
3871+
assert_frame_equal(xp, rs.to_period('M'))
3872+
os.remove(path)
38453873

38463874
def test_to_excel_multiindex(self):
38473875
try:

pandas/tools/plotting.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -452,12 +452,14 @@ def random_color(column):
452452
for i in range(n):
453453
row = df.irow(i).values
454454
y = row
455-
label = None
456455
kls = class_col.iget_value(i)
457456
if com.pprint_thing(kls) not in used_legends:
458457
label = com.pprint_thing(kls)
459458
used_legends.add(label)
460-
ax.plot(x, y, color=random_color(kls), label=label, **kwds)
459+
ax.plot(x, y, color=random_color(kls),
460+
label=label, **kwds)
461+
else:
462+
ax.plot(x, y, color=random_color(kls), **kwds)
461463

462464
for i in range(ncols):
463465
ax.axvline(i, linewidth=1, color='black')

pandas/tseries/index.py

+4
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ def __new__(cls, data=None,
203203
if isinstance(data, DatetimeIndex):
204204
if name is not None:
205205
data.name = name
206+
207+
if tz is not None:
208+
return data.tz_localize(tz)
209+
206210
return data
207211

208212
if issubclass(data.dtype.type, basestring):

pandas/tseries/resample.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ def _get_time_bins(self, axis):
110110

111111
first, last = _get_range_edges(axis, self.freq, closed=self.closed,
112112
base=self.base)
113-
binner = labels = DatetimeIndex(freq=self.freq, start=first, end=last)
113+
tz = axis.tz
114+
binner = labels = DatetimeIndex(freq=self.freq,
115+
start=first.replace(tzinfo=None),
116+
end=last.replace(tzinfo=None), tz=tz)
114117

115118
# a little hack
116119
trimmed = False

pandas/tseries/tests/test_resample.py

+18
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,24 @@ def test_resample_tz_localized(self):
823823
# it works
824824
result = ts_local.resample('D')
825825

826+
# #2245
827+
idx = date_range('2001-09-20 15:59','2001-09-20 16:00', freq='T',
828+
tz='Australia/Sydney')
829+
s = Series([1,2], index=idx)
830+
831+
result = s.resample('D')
832+
ex_index = date_range('2001-09-21', periods=1, freq='D',
833+
tz='Australia/Sydney')
834+
expected = Series([1.5], index=ex_index)
835+
836+
assert_series_equal(result, expected)
837+
838+
# for good measure
839+
result = s.resample('D', kind='period')
840+
ex_index = period_range('2001-09-20', periods=1, freq='D')
841+
expected = Series([1.5], index=ex_index)
842+
assert_series_equal(result, expected)
843+
826844
def test_closed_left_corner(self):
827845
# #1465
828846
s = Series(np.random.randn(21),

pandas/tseries/tests/test_timezones.py

+11
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,17 @@ def test_tz_localize_dti(self):
137137
freq='L')
138138
self.assertRaises(pytz.NonExistentTimeError, dti.tz_localize, 'US/Eastern')
139139

140+
def test_tz_localize_empty_series(self):
141+
# #2248
142+
143+
ts = Series()
144+
145+
ts2 = ts.tz_localize('utc')
146+
self.assertTrue(ts2.index.tz == pytz.utc)
147+
148+
ts2 = ts.tz_localize('US/Eastern')
149+
self.assertTrue(ts2.index.tz == pytz.timezone('US/Eastern'))
150+
140151
def test_astimezone(self):
141152
utc = Timestamp('3/11/2012 22:00', tz='UTC')
142153
expected = utc.tz_convert('US/Eastern')

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
MICRO = 1
208208
ISRELEASED = True
209209
VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
210-
QUALIFIER = 'rc1'
210+
QUALIFIER = ''
211211

212212
FULLVERSION = VERSION
213213
if not ISRELEASED:

0 commit comments

Comments
 (0)