Pandas PDF
Pandas PDF
toolkit
Release 0.17.0
CONTENTS
Whats New
1.1 v0.17.0 (October 9, 2015) . . . . . . . . . . . . . . . .
1.2 v0.16.2 (June 12, 2015) . . . . . . . . . . . . . . . . .
1.3 v0.16.1 (May 11, 2015) . . . . . . . . . . . . . . . . .
1.4 v0.16.0 (March 22, 2015) . . . . . . . . . . . . . . . .
1.5 v0.15.2 (December 12, 2014) . . . . . . . . . . . . . .
1.6 v0.15.1 (November 9, 2014) . . . . . . . . . . . . . . .
1.7 v0.15.0 (October 18, 2014) . . . . . . . . . . . . . . . .
1.8 v0.14.1 (July 11, 2014) . . . . . . . . . . . . . . . . . .
1.9 v0.14.0 (May 31 , 2014) . . . . . . . . . . . . . . . . .
1.10 v0.13.1 (February 3, 2014) . . . . . . . . . . . . . . . .
1.11 v0.13.0 (January 3, 2014) . . . . . . . . . . . . . . . .
1.12 v0.12.0 (July 24, 2013) . . . . . . . . . . . . . . . . . .
1.13 v0.11.0 (April 22, 2013) . . . . . . . . . . . . . . . . .
1.14 v0.10.1 (January 22, 2013) . . . . . . . . . . . . . . . .
1.15 v0.10.0 (December 17, 2012) . . . . . . . . . . . . . .
1.16 v0.9.1 (November 14, 2012) . . . . . . . . . . . . . . .
1.17 v0.9.0 (October 7, 2012) . . . . . . . . . . . . . . . . .
1.18 v0.8.1 (July 22, 2012) . . . . . . . . . . . . . . . . . .
1.19 v0.8.0 (June 29, 2012) . . . . . . . . . . . . . . . . . .
1.20 v.0.7.3 (April 12, 2012) . . . . . . . . . . . . . . . . .
1.21 v.0.7.2 (March 16, 2012) . . . . . . . . . . . . . . . . .
1.22 v.0.7.1 (February 29, 2012) . . . . . . . . . . . . . . .
1.23 v.0.7.0 (February 9, 2012) . . . . . . . . . . . . . . . .
1.24 v.0.6.1 (December 13, 2011) . . . . . . . . . . . . . . .
1.25 v.0.6.0 (November 25, 2011) . . . . . . . . . . . . . . .
1.26 v.0.5.0 (October 24, 2011) . . . . . . . . . . . . . . . .
1.27 v.0.4.3 through v0.4.1 (September 25 - October 9, 2011)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
28
32
42
58
63
69
96
102
129
136
159
170
179
185
196
200
202
202
208
211
212
212
217
218
220
221
Installation
2.1 Python version support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Installing pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
223
223
223
226
Contributing to pandas
3.1 Where to start? . . . . . . . . . . . .
3.2 Bug Reports/Enhancement Requests .
3.3 Working with the code . . . . . . . .
3.4 Contributing to the documentation . .
3.5 Contributing to the code base . . . .
3.6 Contributing your changes to pandas
229
229
230
230
233
235
238
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Package overview
5.1 Data structures at a glance . . .
5.2 Mutability and copying of data .
5.3 Getting Support . . . . . . . .
5.4 Credits . . . . . . . . . . . . .
5.5 Development Team . . . . . . .
5.6 License . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
245
245
246
246
246
246
246
10 Minutes to pandas
6.1 Object Creation . . .
6.2 Viewing Data . . . .
6.3 Selection . . . . . .
6.4 Missing Data . . . .
6.5 Operations . . . . .
6.6 Merge . . . . . . . .
6.7 Grouping . . . . . .
6.8 Reshaping . . . . .
6.9 Time Series . . . . .
6.10 Categoricals . . . .
6.11 Plotting . . . . . . .
6.12 Getting Data In/Out
6.13 Gotchas . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
249
249
251
252
257
257
260
262
263
265
266
268
269
271
Tutorials
7.1 Internal Guides . . . . . . . . . . . . . . . . . .
7.2 pandas Cookbook . . . . . . . . . . . . . . . .
7.3 Lessons for New pandas Users . . . . . . . . . .
7.4 Practical data analysis with Python . . . . . . .
7.5 Excel charts with pandas, vincent and xlsxwriter
7.6 Various Tutorials . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
273
273
273
274
274
274
274
Cookbook
8.1 Idioms . . . . . . . . .
8.2 Selection . . . . . . . .
8.3 MultiIndexing . . . . .
8.4 Missing Data . . . . . .
8.5 Grouping . . . . . . . .
8.6 Timeseries . . . . . . .
8.7 Merge . . . . . . . . . .
8.8 Plotting . . . . . . . . .
8.9 Data In/Out . . . . . . .
8.10 Computation . . . . . .
8.11 Timedeltas . . . . . . .
8.12 Aliasing Axis Names . .
8.13 Creating Example Data .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
277
277
280
284
288
289
297
298
299
300
303
304
305
306
ii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9.4
9.5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
335
335
336
337
337
344
352
358
366
369
372
373
377
377
384
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
387
388
391
391
393
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
395
395
396
397
397
403
404
404
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
407
407
408
410
412
413
416
419
421
422
423
425
427
430
441
443
443
444
444
446
449
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
453
453
459
468
470
471
474
15 Computational tools
15.1 Statistical functions . . . . . . . . . . . .
15.2 Moving (rolling) statistics / moments . . .
15.3 Expanding window moment functions . . .
15.4 Exponentially weighted moment functions
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
479
479
483
491
492
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
497
497
499
500
501
502
516
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
519
520
524
525
526
529
533
534
536
538
545
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
573
573
574
579
580
581
585
585
588
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
589
590
590
591
594
596
602
iv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20.7
20.8
20.9
20.10
20.11
20.12
21 Time Deltas
21.1 Parsing . . . . . . . .
21.2 Operations . . . . . .
21.3 Reductions . . . . . .
21.4 Frequency Conversion
21.5 Attributes . . . . . . .
21.6 TimedeltaIndex . . . .
21.7 Resampling . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
614
616
619
625
626
627
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
637
637
638
642
643
644
645
648
22 Categorical Data
22.1 Object Creation . . . . .
22.2 Description . . . . . . .
22.3 Working with categories
22.4 Sorting and Order . . .
22.5 Comparisons . . . . . .
22.6 Operations . . . . . . .
22.7 Data munging . . . . .
22.8 Getting Data In/Out . .
22.9 Missing Data . . . . . .
22.10 Differences to Rs factor
22.11 Gotchas . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
649
649
652
653
656
658
660
661
665
666
667
668
23 Plotting
23.1 Basic Plotting: plot . . . . . .
23.2 Other Plots . . . . . . . . . . .
23.3 Plotting with Missing Data . . .
23.4 Plotting Tools . . . . . . . . . .
23.5 Plot Formatting . . . . . . . . .
23.6 Plotting directly with matplotlib
23.7 Trellis plotting interface . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
673
673
676
707
708
716
739
740
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
755
756
780
788
795
801
802
802
805
832
841
845
847
847
848
851
v
25.1
25.2
25.3
25.4
25.5
25.6
25.7
Yahoo! Finance . . . . .
Yahoo! Finance Options
Google Finance . . . . .
FRED . . . . . . . . . .
Fama/French . . . . . .
World Bank . . . . . . .
Google Analytics . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
851
852
854
854
855
855
858
26 Enhancing Performance
861
26.1 Cython (Writing C extensions for pandas) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 861
26.2 Using numba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865
26.3 Expression Evaluation via eval() (Experimental) . . . . . . . . . . . . . . . . . . . . . . . . . . . 867
27 Sparse data structures
27.1 SparseArray . . . . . . . .
27.2 SparseList . . . . . . . . .
27.3 SparseIndex objects . . . .
27.4 Interaction with scipy.sparse
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
875
877
877
878
878
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
883
883
884
886
886
887
889
889
890
890
890
891
29 rpy2 / R interface
29.1 Updating your code to use rpy2 functions
29.2 R interface with rpy2 . . . . . . . . . . .
29.3 Transferring R data sets into Python . . .
29.4 Converting DataFrames into R objects . .
29.5 Calling R functions with pandas objects .
29.6 High-level interface to R estimators . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
893
893
894
894
894
895
895
30 pandas Ecosystem
30.1 Statistics and Machine Learning
30.2 Visualization . . . . . . . . . .
30.3 IDE . . . . . . . . . . . . . . .
30.4 API . . . . . . . . . . . . . . .
30.5 Domain Specific . . . . . . . .
30.6 Out-of-core . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
897
897
897
898
899
899
899
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
901
901
907
907
907
908
vi
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
913
913
914
916
918
919
921
921
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
923
923
924
925
929
930
932
934
34 API Reference
34.1 Input/Output . . . . . .
34.2 General functions . . . .
34.3 Series . . . . . . . . . .
34.4 DataFrame . . . . . . .
34.5 Panel . . . . . . . . . .
34.6 Panel4D . . . . . . . .
34.7 Index . . . . . . . . . .
34.8 CategoricalIndex . . . .
34.9 DatetimeIndex . . . . .
34.10 TimedeltaIndex . . . . .
34.11 GroupBy . . . . . . . .
34.12 General utility functions
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
935
935
963
1006
1180
1373
1465
1519
1552
1579
1612
1634
1656
.
.
.
.
.
.
.
35 Internals
1669
35.1 Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1669
35.2 Subclassing pandas Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1670
36 Release Notes
36.1 pandas 0.17.0
36.2 pandas 0.16.2
36.3 pandas 0.16.1
36.4 pandas 0.16.0
36.5 pandas 0.15.2
36.6 pandas 0.15.1
36.7 pandas 0.15.0
36.8 pandas 0.14.1
36.9 pandas 0.14.0
36.10 pandas 0.13.1
36.11 pandas 0.13.0
36.12 pandas 0.12.0
36.13 pandas 0.11.0
36.14 pandas 0.10.1
36.15 pandas 0.10.0
36.16 pandas 0.9.1
36.17 pandas 0.9.0
36.18 pandas 0.8.1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1675
1675
1679
1680
1682
1684
1686
1687
1689
1691
1694
1697
1711
1718
1724
1726
1731
1733
1738
vii
36.19
36.20
36.21
36.22
36.23
36.24
36.25
36.26
36.27
36.28
36.29
36.30
36.31
pandas 0.8.0
pandas 0.7.3
pandas 0.7.2
pandas 0.7.1
pandas 0.7.0
pandas 0.6.1
pandas 0.6.0
pandas 0.5.0
pandas 0.4.3
pandas 0.4.2
pandas 0.4.1
pandas 0.4.0
pandas 0.3.0
viii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1740
1745
1746
1748
1749
1755
1757
1761
1765
1766
1767
1769
1774
1777
PDF Version
Zipped HTML Date: October 09, 2015 Version: 0.17.0
Binary Installers: http://pypi.python.org/pypi/pandas
Source Repository: http://github.com/pydata/pandas
Issues & Ideas: https://github.com/pydata/pandas/issues
Q&A Support: http://stackoverflow.com/questions/tagged/pandas
Developer Mailing List: http://groups.google.com/group/pydata
pandas is a Python package providing fast, flexible, and expressive data structures designed to make working with
relational or labeled data both easy and intuitive. It aims to be the fundamental high-level building block for doing
practical, real world data analysis in Python. Additionally, it has the broader goal of becoming the most powerful
and flexible open source data analysis / manipulation tool available in any language. It is already well on its way
toward this goal.
pandas is well suited for many different kinds of data:
Tabular data with heterogeneously-typed columns, as in an SQL table or Excel spreadsheet
Ordered and unordered (not necessarily fixed-frequency) time series data.
Arbitrary matrix data (homogeneously typed or heterogeneous) with row and column labels
Any other form of observational / statistical data sets. The data actually need not be labeled at all to be placed
into a pandas data structure
The two primary data structures of pandas, Series (1-dimensional) and DataFrame (2-dimensional), handle the
vast majority of typical use cases in finance, statistics, social science, and many areas of engineering. For R users,
DataFrame provides everything that Rs data.frame provides and much more. pandas is built on top of NumPy
and is intended to integrate well within a scientific computing environment with many other 3rd party libraries.
Here are just a few of the things that pandas does well:
Easy handling of missing data (represented as NaN) in floating point as well as non-floating point data
Size mutability: columns can be inserted and deleted from DataFrame and higher dimensional objects
Automatic and explicit data alignment: objects can be explicitly aligned to a set of labels, or the user can
simply ignore the labels and let Series, DataFrame, etc. automatically align the data for you in computations
Powerful, flexible group by functionality to perform split-apply-combine operations on data sets, for both aggregating and transforming data
Make it easy to convert ragged, differently-indexed data in other Python and NumPy data structures into
DataFrame objects
Intelligent label-based slicing, fancy indexing, and subsetting of large data sets
Intuitive merging and joining data sets
Flexible reshaping and pivoting of data sets
Hierarchical labeling of axes (possible to have multiple labels per tick)
Robust IO tools for loading data from flat files (CSV and delimited), Excel files, databases, and saving / loading
data from the ultrafast HDF5 format
Time series-specific functionality: date range generation and frequency conversion, moving window statistics,
moving window linear regressions, date shifting and lagging, etc.
CONTENTS
Many of these principles are here to address the shortcomings frequently experienced using other languages / scientific
research environments. For data scientists, working with data is typically divided into multiple stages: munging and
cleaning data, analyzing / modeling it, then organizing the results of the analysis into a form suitable for plotting or
tabular display. pandas is the ideal tool for all of these tasks.
Some other notes
pandas is fast. Many of the low-level algorithmic bits have been extensively tweaked in Cython code. However,
as with anything else generalization usually sacrifices performance. So if you focus on one feature for your
application you may be able to create a faster specialized tool.
pandas is a dependency of statsmodels, making it an important part of the statistical computing ecosystem in
Python.
pandas has been used extensively in production in financial applications.
Note: This documentation assumes general familiarity with NumPy. If you havent used NumPy much or at all, do
invest some time in learning about NumPy first.
See the package overview for more detail about whats in the library.
CONTENTS
CHAPTER
ONE
WHATS NEW
becomes
from pandas_datareader import data, wb
Highlights include:
Release the Global Interpreter Lock (GIL) on some cython operations, see here
Plotting methods are now available as attributes of the .plot accessor, see here
The sorting API has been revamped to remove some long-time inconsistencies, see here
Support for a datetime64[ns] with timezones as a first-class dtype, see here
The default for to_datetime will now be to raise when presented with unparseable formats, previously
this would return the original input. Also, date parse functions now return consistent results. See here
The default for dropna in HDFStore has changed to False, to store by default all rows even if they are all
NaN, see here
Datetime accessor (dt) now supports Series.dt.strftime to generate formatted strings for datetimelikes, and Series.dt.total_seconds to generate each duration of the timedelta in seconds. See here
Period and PeriodIndex can handle multiplied freq like 3D, which corresponding to 3 days span. See here
Development installed versions of pandas will now have PEP440 compliant version strings (GH9518)
Development support for benchmarking with the Air Speed Velocity library (GH8361)
Support for reading SAS xport files, see here
Documentation comparing SAS to pandas, see here
Removal of the automatic TimeSeries broadcasting, deprecated since 0.8.0, see here
Display format with plain text can optionally align with Unicode East Asian Width, see here
Compatibility with Python 3.5 (GH11097)
Compatibility with matplotlib 1.5.0 (GH11111)
Check the API Changes and deprecations before updating.
Whats new in v0.17.0
New features
Datetime with TZ
Releasing the GIL
Plot submethods
Additional methods for dt accessor
* strftime
* total_seconds
Period Frequency Enhancement
Support for SAS XPORT files
Support for Math Functions in .eval()
Changes to Excel with MultiIndex
Google BigQuery Enhancements
Display Alignment with Unicode East Asian Width
Other enhancements
Backwards incompatible API changes
Changes to sorting API
Changes to to_datetime and to_timedelta
* Error handling
* Consistent Parsing
Changes to Index Comparisons
Changes to Boolean Comparisons vs. None
HDFStore dropna behavior
Changes to display.precision option
Changes to Categorical.unique
Changes to bool passed as header in Parsers
Other API Changes
Deprecations
Removal of prior version deprecations/changes
Performance Improvements
Bug Fixes
performance issues with a large number rows. See the docs for more details. (GH8260, GH10763, GH11034).
The new implementation allows for having a single-timezone across all rows, with operations in a performant manner.
In [1]: df = DataFrame({'A' : date_range('20130101',periods=3),
...:
'B' : date_range('20130101',periods=3,tz='US/Eastern'),
...:
'C' : date_range('20130101',periods=3,tz='CET')})
...:
In [2]: df
Out[2]:
A
B
C
0 2013-01-01 2013-01-01 00:00:00-05:00 2013-01-01 00:00:00+01:00
1 2013-01-02 2013-01-02 00:00:00-05:00 2013-01-02 00:00:00+01:00
2 2013-01-03 2013-01-03 00:00:00-05:00 2013-01-03 00:00:00+01:00
In [3]: df.dtypes
Out[3]:
A
datetime64[ns]
B
datetime64[ns, US/Eastern]
C
datetime64[ns, CET]
dtype: object
In [4]: df.B
Out[4]:
0
2013-01-01 00:00:00-05:00
1
2013-01-02 00:00:00-05:00
2
2013-01-03 00:00:00-05:00
Name: B, dtype: datetime64[ns, US/Eastern]
In [5]: df.B.dt.tz_localize(None)
Out[5]:
0
2013-01-01
1
2013-01-02
2
2013-01-03
Name: B, dtype: datetime64[ns]
This uses a new-dtype representation as well, that is very similar in look-and-feel to its numpy cousin
datetime64[ns]
In [6]: df['B'].dtype
Out[6]: datetime64[ns, US/Eastern]
In [7]: type(df['B'].dtype)
Out[7]: pandas.core.dtypes.DatetimeTZDtype
Note: There is a slightly different string repr for the underlying DatetimeIndex as a result of the dtype changes,
but functionally these are the same.
Previous Behavior:
In [1]: pd.date_range('20130101',periods=3,tz='US/Eastern')
Out[1]: DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00',
'2013-01-03 00:00:00-05:00'],
dtype='datetime64[ns]', freq='D', tz='US/Eastern')
In [2]: pd.date_range('20130101',periods=3,tz='US/Eastern').dtype
Out[2]: dtype('<M8[ns]')
New Behavior:
1.1. v0.17.0 (October 9, 2015)
In [8]: pd.date_range('20130101',periods=3,tz='US/Eastern')
Out[8]:
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00',
'2013-01-03 00:00:00-05:00'],
dtype='datetime64[ns, US/Eastern]', freq='D')
In [9]: pd.date_range('20130101',periods=3,tz='US/Eastern').dtype
Out[9]: datetime64[ns, US/Eastern]
Releasing of the GIL could benefit an application that uses threads for user interactions (e.g. QT), or performing
multi-threaded computations. A nice example of a library that can handle these types of computation-in-parallel is the
dask library.
Plot submethods
The Series and DataFrame .plot() method allows for customizing plot types by supplying the kind keyword
arguments. Unfortunately, many of these kinds of plots use different required and optional keyword arguments, which
makes it difficult to discover what any given plot kind uses out of the dozens of possible arguments.
To alleviate this issue, we have added a new, optional plotting interface, which exposes each kind of plot as a
method of the .plot attribute. Instead of writing series.plot(kind=<kind>, ...), you can now also
use series.plot.<kind>(...):
In [10]: df = pd.DataFrame(np.random.rand(10, 2), columns=['a', 'b'])
In [11]: df.plot.bar()
As a result of this change, these methods are now all discoverable via tab-completion:
In [12]: df.plot.<TAB>
df.plot.area
df.plot.barh
df.plot.bar
df.plot.box
df.plot.density
df.plot.hexbin
df.plot.hist
df.plot.kde
df.plot.line
df.plot.pie
df.plot.scatter
Each method signature only includes relevant arguments. Currently, these are limited to required arguments, but in the
future these will include optional arguments, as well. For an overview, see the new Plotting API documentation.
Additional methods for dt accessor
strftime
We are now supporting a Series.dt.strftime method for datetime-likes to generate a formatted string
(GH10110). Examples:
# DatetimeIndex
In [13]: s = pd.Series(pd.date_range('20130101', periods=4))
In [14]: s
Out[14]:
0
2013-01-01
1
2013-01-02
2
2013-01-03
3
2013-01-04
dtype: datetime64[ns]
In [15]: s.dt.strftime('%Y/%m/%d')
Out[15]:
0
2013/01/01
1
2013/01/02
2
2013/01/03
3
2013/01/04
dtype: object
# PeriodIndex
In [16]: s = pd.Series(pd.period_range('20130101', periods=4))
In [17]: s
Out[17]:
0
2013-01-01
1
2013-01-02
2
2013-01-03
3
2013-01-04
dtype: object
In [18]: s.dt.strftime('%Y/%m/%d')
Out[18]:
0
2013/01/01
1
2013/01/02
2
2013/01/03
3
2013/01/04
dtype: object
The string format is as the python standard library and details can be found here
total_seconds
pd.Series of type timedelta64 has new method .dt.total_seconds() returning the duration of the
timedelta in seconds (GH10817)
# TimedeltaIndex
In [19]: s = pd.Series(pd.timedelta_range('1 minutes', periods=4))
In [20]: s
Out[20]:
0
0 days 00:01:00
1
1 days 00:01:00
2
2 days 00:01:00
3
3 days 00:01:00
dtype: timedelta64[ns]
In [21]: s.dt.total_seconds()
Out[21]:
0
60
1
86460
2
172860
3
259260
dtype: float64
In [23]: p
Out[23]: Period('2015-08-01', '3D')
In [24]: p + 1
Out[24]: Period('2015-08-04', '3D')
In [25]: p - 2
Out[25]: Period('2015-07-26', '3D')
In [26]: p.to_timestamp()
Out[26]: Timestamp('2015-08-01 00:00:00')
In [27]: p.to_timestamp(how='E')
Out[27]: Timestamp('2015-08-03 00:00:00')
In [29]: idx
Out[29]: PeriodIndex(['2015-08-01', '2015-08-03', '2015-08-05', '2015-08-07'], dtype='int64', freq='2
In [30]: idx + 1
Out[30]: PeriodIndex(['2015-08-03', '2015-08-05', '2015-08-07', '2015-08-09'], dtype='int64', freq='2
The support math functions are sin, cos, exp, log, expm1, log1p, sqrt, sinh, cosh, tanh, arcsin, arccos, arctan, arccosh,
arcsinh, arctanh, abs and arctan2.
These functions map to the intrinsics for the NumExpr engine. For the Python engine, they are mapped to NumPy
calls.
Changes to Excel with MultiIndex
In version 0.16.2 a DataFrame with MultiIndex columns could not be written to Excel via to_excel. That
functionality has been added (GH10564), along with updating read_excel so that the data can be read back with, no
loss of information, by specifying which columns/rows make up the MultiIndex in the header and index_col
parameters (GH4679)
See the documentation for more details.
In [31]: df = pd.DataFrame([[1,2,3,4], [5,6,7,8]],
....:
columns = pd.MultiIndex.from_product([['foo','bar'],['a','b']],
....:
names = ['col1', 'col2']),
....:
index = pd.MultiIndex.from_product([['j'], ['l', 'k']],
....:
names = ['i1', 'i2']))
....:
In [32]: df
Out[32]:
col1 foo
bar
col2
a b
a
i1 i2
j l
1 2
3
k
5 6
7
b
4
8
In [33]: df.to_excel('test.xlsx')
In [34]: df = pd.read_excel('test.xlsx', header=[0,1], index_col=[0,1])
In [35]: df
Out[35]:
col1 foo
bar
col2
a b
a
i1 i2
j l
1 2
3
k
5 6
7
b
4
8
Previously, it was necessary to specify the has_index_names argument in read_excel, if the serialized data
had index names. For version 0.17.0 the ouptput format of to_excel has been changed to make this keyword
unnecessary - the change is shown below.
Old
New
10
Warning: Excel files saved in version 0.16.2 or prior that had index names will still able to be read in, but the
has_index_names argument must specified to True.
11
_merge value
left_only
right_only
both
Previous Behavior:
12
New Behavior:
In [46]: pd.concat([foo, bar, baz], 1)
Out[46]:
foo 0 1
0
1 1 4
1
2 2 5
Added a DataFrame.round method to round the values to a variable number of decimal places (GH10568).
In [49]: df = pd.DataFrame(np.random.random([3, 3]), columns=['A', 'B', 'C'],
....: index=['first', 'second', 'third'])
....:
In [50]: df
Out[50]:
first
second
third
A
0.179356
0.851401
0.597175
B
0.908835
0.203918
0.113613
C
0.571981
0.105336
0.326599
In [51]: df.round(2)
Out[51]:
A
B
C
first
0.18 0.91 0.57
second 0.85 0.20 0.11
third
0.60 0.11 0.33
In [52]: df.round({'A': 0, 'C': 2})
Out[52]:
A
B
C
first
0 0.908835 0.57
second 1 0.203918 0.11
third
1 0.113613 0.33
drop_duplicates and duplicated now accept a keep keyword to target first, last, and all duplicates.
1.1. v0.17.0 (October 9, 2015)
13
Reindex now has a tolerance argument that allows for finer control of Limits on filling while reindexing
(GH10411):
In [57]: df = pd.DataFrame({'x': range(5),
....:
't': pd.date_range('2000-01-01', periods=5)})
....:
In [58]: df.reindex([0.1, 1.9, 3.5],
....:
method='nearest',
....:
tolerance=0.2)
....:
Out[58]:
t
x
0.1 2000-01-01
0
1.9 2000-01-03
2
3.5
NaT NaN
tolerance is also exposed by the lower level Index.get_indexer and Index.get_loc methods.
Added functionality to use the base argument when resampling a TimeDeltaIndex (GH10530)
DatetimeIndex can be instantiated using strings contains NaT (GH7599)
14
15
Replacement
Series.sort_values()
Series.sort_values(inplace=True)
DataFrame.sort_values(by=...)
Replacement
Series.sort_index()
Series.sort_index(level=...)
DataFrame.sort_index()
DataFrame.sort_index(level=...)
DataFrame.sort_index()
We have also deprecated and changed similar methods in two Series-like classes, Index and Categorical.
Previous
* Index.order()
* Categorical.order()
Replacement
Index.sort_values()
Categorical.sort_values()
The default for pd.to_datetime error handling has changed to errors=raise. In prior versions it was
errors=ignore. Furthermore, the coerce argument has been deprecated in favor of errors=coerce.
This means that invalid parsing will raise rather that return the original input as in previous versions. (GH10636)
16
Previous Behavior:
In [2]: pd.to_datetime(['2009-07-31', 'asd'])
Out[2]: array(['2009-07-31', 'asd'], dtype=object)
New Behavior:
In [3]: pd.to_datetime(['2009-07-31', 'asd'])
ValueError: Unknown string format
The string parsing of to_datetime, Timestamp and DatetimeIndex has been made consistent. (GH7599)
Prior to v0.17.0, Timestamp and to_datetime may parse year-only datetime-string incorrectly using todays
date, otherwise DatetimeIndex uses the beginning of the year. Timestamp and to_datetime may raise
ValueError in some types of datetime-string which DatetimeIndex can parse, such as a quarterly string.
Previous Behavior:
In [1]: Timestamp('2012Q2')
Traceback
...
ValueError: Unable to parse 2012Q2
# Results in today's date.
In [2]: Timestamp('2014')
Out [2]: 2014-08-12 00:00:00
Note:
If you want to perform calculations based on todays date, use Timestamp.now() and
pandas.tseries.offsets.
17
New Behavior:
In [8]: pd.Index([1, 2, 3]) == pd.Index([1, 4, 5])
Out[8]: array([ True, False, False], dtype=bool)
In [9]: pd.Index([1, 2, 3]) == pd.Index([2])
ValueError: Lengths must match to compare
In [10]: pd.Index([1, 2, 3]) == pd.Index([1, 2])
ValueError: Lengths must match to compare
Note that this is different from the numpy behavior where a comparison can be broadcast:
In [69]: np.array([1, 2, 3]) == np.array([1])
Out[69]: array([ True, False, False], dtype=bool)
18
In [73]: s
Out[73]:
0
0
1
NaN
2
2
dtype: float64
Previous Behavior:
In [5]: s==None
TypeError: Could not compare <type 'NoneType'> type with Series
New Behavior:
In [74]: s==None
Out[74]:
0
False
1
False
2
False
dtype: bool
Warning:
You generally will want to use isnull/notnull for these types of comparisons, as
isnull/notnull tells you which elements are null. One has to be mindful that nans dont compare equal,
but Nones do. Note that Pandas/numpy uses the fact that np.nan != np.nan, and treats None like np.nan.
In [76]: None == None
Out[76]: True
In [77]: np.nan == np.nan
Out[77]: False
19
1
2
NaN
2
NaN
NaN
In [28]:
df_with_missing.to_hdf('file.h5',
'df_with_missing',
format='table',
mode='w')
pd.read_hdf('file.h5', 'df_with_missing')
Out [28]:
col1
0
0
2
2
col2
1
NaN
New Behavior:
In [80]: df_with_missing.to_hdf('file.h5',
....:
'df_with_missing',
....:
format='table',
....:
mode='w')
....:
In [81]: pd.read_hdf('file.h5', 'df_with_missing')
Out[81]:
col1 col2
0
0
1
1
NaN
NaN
2
2
NaN
If interpreting precision as significant figures this did work for scientific notation but that same interpretation did not
work for values with standard formatting. It was also out of step with how numpy handles formatting.
Going forward the value of display.precision will directly control the number of places after the decimal, for
regular formatting as well as scientific notation, similar to how numpys precision print option works.
In [82]: pd.set_option('display.precision', 2)
In [83]: pd.DataFrame({'x': [123.456789]})
Out[83]:
x
0 123.46
20
To preserve output behavior with prior versions the default value of display.precision has been reduced to 6
from 7.
Changes to Categorical.unique
Categorical.unique now returns new Categoricals with categories and codes that are unique, rather
than returning np.array (GH10508)
unordered category: values and categories are sorted by appearance order.
ordered category: values are sorted by appearance order, categories keep existing order.
In [84]: cat = pd.Categorical(['C', 'A', 'B', 'C'],
....:
categories=['A', 'B', 'C'],
....:
ordered=True)
....:
In [85]: cat
Out[85]:
[C, A, B, C]
Categories (3, object): [A < B < C]
In [86]: cat.unique()
Out[86]:
[C, A, B]
Categories (3, object): [A < B < C]
In [87]: cat = pd.Categorical(['C', 'A', 'B', 'C'],
....:
categories=['A', 'B', 'C'])
....:
In [88]: cat
Out[88]:
[C, A, B, C]
Categories (3, object): [A, B, C]
In [89]: cat.unique()
Out[89]:
[C, A, B]
Categories (3, object): [C, A, B]
21
Methods
weekday, isoweekday
date, now, replace, to_datetime, today
to_datetime64 (unchanged)
All other public methods (names not beginning with underscores)
Deprecations
For Series the following indexing functions are deprecated (GH10177).
Deprecated Function
.irow(i)
.iget(i)
.iget_value(i)
Replacement
.iloc[i] or .iat[i]
.iloc[i] or .iat[i]
.iloc[i] or .iat[i]
Replacement
.iloc[i]
.iloc[i, j] or .iat[i, j]
.iloc[:, j]
Note: These indexing function have been deprecated in the documentation since 0.11.0.
Categorical.name was deprecated to make Categorical more numpy.ndarray like.
Series(cat, name="whatever") instead (GH10482).
Use
Setting missing values (NaN) in a Categoricals categories will issue a warning (GH10748). You can
still have missing values in the values.
drop_duplicates and duplicateds take_last keyword was deprecated in favor of keep. (GH6511,
GH8505)
22
Series.nsmallest and nlargests take_last keyword was deprecated in favor of keep. (GH10792)
DataFrame.combineAdd and DataFrame.combineMult are deprecated. They can easily be
replaced by using the add and mul methods: DataFrame.add(other, fill_value=0) and
DataFrame.mul(other, fill_value=1.) (GH10735).
TimeSeries deprecated in favor of Series (note that this has been an alias since 0.13.0), (GH10890)
SparsePanel deprecated and will be removed in a future version (GH11157).
Series.is_time_series deprecated in favor of Series.index.is_all_dates (GH11135)
Legacy offsets (like A@JAN) listed in here are deprecated (note that this has been alias since 0.8.0),
(GH10878)
WidePanel deprecated in favor of Panel, LongPanel in favor of DataFrame (note these have been
aliases since < 0.11.0), (GH10892)
DataFrame.convert_objects has been deprecated in favor of type-specific
pd.to_datetime, pd.to_timestamp and pd.to_numeric (new in 0.17.0) (GH11133).
functions
In [91]: df = DataFrame(np.random.randn(5,2),columns=list('AB'),index=date_range('20130101',peri
In [92]: df
Out[92]:
A
B
2013-01-01 0.471435 -1.190976
2013-01-02 1.432707 -0.312652
2013-01-03 -0.720589 0.887163
2013-01-04 0.859588 -0.636524
2013-01-05 0.015696 -2.242685
Previously
In [3]: df + df.A
FutureWarning: TimeSeries broadcasting along DataFrame index by default is deprecated.
Please use DataFrame.<op> to explicitly broadcast arithmetic operations along the index
Out[3]:
A
B
2013-01-01 0.942870 -0.719541
2013-01-02 2.865414 1.120055
2013-01-03 -1.441177 0.166574
2013-01-04 1.719177 0.223065
2013-01-05 0.031393 -2.226989
Current
23
In [93]: df.add(df.A,axis='index')
Out[93]:
A
B
2013-01-01 0.942870 -0.719541
2013-01-02 2.865414 1.120055
2013-01-03 -1.441177 0.166574
2013-01-04 1.719177 0.223065
2013-01-05 0.031393 -2.226989
24
25
header
kwarg
not
setting
the
Series.name
or
the
Bug in groupby.var which caused variance to be inaccurate for small float values (GH10448)
Bug in Series.plot(kind=hist) Y Label not informative (GH10485)
Bug in read_csv when using a converter which generates a uint8 type (GH9266)
Bug causes memory leak in time-series line and area plot (GH9003)
Bug when setting a Panel sliced along the major or minor axes when the right-hand side is a DataFrame
(GH11014)
Bug that returns None and does not raise NotImplementedError when operator functions (e.g. .add) of
Panel are not implemented (GH7692)
Bug in line and kde plot cannot accept multiple colors when subplots=True (GH9894)
Bug in DataFrame.plot raises ValueError when color name is specified by multiple characters
(GH10387)
Bug in left and right align of Series with MultiIndex may be inverted (GH10665)
26
Bug in left and right join of with MultiIndex may be inverted (GH10741)
Bug in read_stata when reading a file with a different order set in columns (GH10757)
Bug in Categorical may not representing properly when category contains tz or Period (GH10713)
Bug in Categorical.__iter__ may not returning correct datetime and Period (GH10713)
Bug in indexing with a PeriodIndex on an object with a PeriodIndex (GH4125)
Bug in read_csv with engine=c: EOF preceded by a comment, blank line, etc. was not handled correctly
(GH10728, GH10548)
Reading famafrench data via DataReader results in HTTP 404 error because of the website url is changed
(GH10591).
Bug in read_msgpack where DataFrame to decode has duplicate column names (GH9618)
Bug in io.common.get_filepath_or_buffer which caused reading of valid S3 files to fail if the
bucket also contained keys for which the user does not have read permission (GH10604)
Bug in vectorised setting of timestamp columns with python datetime.date and numpy datetime64
(GH10408, GH10412)
Bug in Index.take may add unnecessary freq attribute (GH10791)
Bug in merge with empty DataFrame may raise IndexError (GH10824)
Bug in to_latex where unexpected keyword argument for some documented arguments (GH10888)
Bug in indexing of large DataFrame where IndexError is uncaught (GH10645 and GH10692)
Bug in read_csv when using the nrows or chunksize parameters if file contains only a header line
(GH9535)
Bug in serialization of category types in HDF5 in presence of alternate encodings. (GH10366)
Bug in pd.DataFrame when constructing an empty DataFrame with a string dtype (GH9428)
Bug in pd.DataFrame.diff when DataFrame is not consolidated (GH10907)
Bug in pd.unique for arrays with the datetime64 or timedelta64 dtype that meant an array with object
dtype was returned instead the original dtype (GH9431)
Bug in Timedelta raising error when slicing from 0s (GH10583)
Bug in DatetimeIndex.take and TimedeltaIndex.take may not raise IndexError against invalid
index (GH10295)
Bug in Series([np.nan]).astype(M8[ms]),
(GH10747)
27
Bug where pd.read_gbq throws ValueError when Bigquery returns zero rows (GH10273)
Bug in to_json which was causing segmentation fault when serializing 0-rank ndarray (GH9576)
Bug in plotting functions may raise IndexError when plotted on GridSpec (GH10819)
Bug in plot result may show unnecessary minor ticklabels (GH10657)
Bug in groupby incorrect computation for aggregation on DataFrame with NaT (E.g first, last, min).
(GH10590, GH11010)
Bug when constructing DataFrame where passing a dictionary with only scalar values and specifying columns
did not raise an error (GH10856)
Bug in .var() causing roundoff errors for highly similar values (GH10242)
Bug in DataFrame.plot(subplots=True) with duplicated columns outputs incorrect result (GH10962)
Bug in Index arithmetic may result in incorrect class (GH10638)
Bug in date_range results in empty if freq is negative annualy, quarterly and monthly (GH11018)
Bug in DatetimeIndex cannot infer negative freq (GH11018)
Remove use of some deprecated numpy comparison operations, mainly in tests. (GH10569)
Bug in Index dtype may not applied properly (GH11017)
Bug in io.gbq when testing for minimum google api client version (GH10652)
Bug in DataFrame construction from nested dict with timedelta keys (GH11129)
Bug in .fillna against may raise TypeError when data contains datetime dtype (GH7095, GH11153)
Bug in .groupby when number of keys to group by is same as length of index (GH11185)
Bug in convert_objects where converted values might not be returned if all null and coerce (GH9589)
Bug in convert_objects where copy keyword was not respected (GH9589)
28
The logic flows from inside out, and function names are separated from their keyword arguments. This can be rewritten
as
(df.pipe(h)
.pipe(g, arg1=1)
.pipe(f, arg2=2, arg3=3)
)
Now both the code and the logic flow from top to bottom. Keyword arguments are next to their functions. Overall the
code is much more readable.
In the example above, the functions f, g, and h each expected the DataFrame as the first positional argument. When
the function you wish to apply takes its data anywhere other than the first argument, pass a tuple of (function,
keyword) indicating where the DataFrame should flow. For example:
In [1]: import statsmodels.formula.api as sm
In [2]: bb = pd.read_csv('data/baseball.csv', index_col='id')
# sm.poisson takes (formula, data)
In [3]: (bb.query('h > 0')
...:
.assign(ln_h = lambda df: np.log(df.h))
...:
.pipe((sm.poisson, 'data'), 'hr ~ ln_h + year + g + C(lg)')
...:
.fit()
...:
.summary()
...: )
...:
Optimization terminated successfully.
Current function value: 2.116284
Iterations 24
Out[3]:
<class 'statsmodels.iolib.summary.Summary'>
"""
Poisson Regression Results
==============================================================================
Dep. Variable:
hr
No. Observations:
68
Model:
Poisson
Df Residuals:
63
Method:
MLE
Df Model:
4
Date:
Fri, 09 Oct 2015
Pseudo R-squ.:
0.6878
Time:
20:59:49
Log-Likelihood:
-143.91
converged:
True
LL-Null:
-460.91
LLR p-value:
6.774e-136
===============================================================================
coef
std err
z
P>|z|
[95.0% Conf. Int.]
------------------------------------------------------------------------------Intercept
-1267.3636
457.867
-2.768
0.006
-2164.767 -369.960
C(lg)[T.NL]
-0.2057
0.101
-2.044
0.041
-0.403
-0.008
ln_h
0.9280
0.191
4.866
0.000
0.554
1.302
29
year
0.6301
0.228
2.762
0.006
0.183
1.077
g
0.0099
0.004
2.754
0.006
0.003
0.017
===============================================================================
"""
The pipe method is inspired by unix pipes, which stream text through processes. More recently dplyr and magrittr
have introduced the popular (%>%) pipe operator for R.
See the documentation for more. (GH10129)
Other Enhancements
Added rsplit to Index/Series StringMethods (GH10303)
Removed the hard-coded size limits on the DataFrame HTML representation in the IPython notebook, and
leave this to IPython itself (only for IPython v3.0 or greater). This eliminates the duplicate scroll bars that
appeared in the notebook with large frames (GH10231).
Note that the notebook has a toggle output scrolling feature to limit the display of very large frames
(by clicking left of the output). You can also configure the way DataFrames are displayed using the pandas
options, see here here.
axis parameter of DataFrame.quantile now accepts also index and column. (GH9543)
30
Bug where Panel.from_dict does not set dtype when specified (GH10058)
Bug in Index.union raises AttributeError when passing array-likes. (GH10149)
Bug in Timestamps microsecond, quarter, dayofyear, week and daysinmonth properties return np.int type, not built-in int. (GH10050)
Bug in NaT raises AttributeError when accessing to daysinmonth, dayofweek properties.
(GH10096)
Bug in Index repr when using the max_seq_items=None setting (GH10182).
Bug in getting timezone data with dateutil on various platforms ( GH9059, GH8639, GH9663, GH10121)
Bug in displaying datetimes with mixed frequencies; display ms datetimes to the proper precision. (GH10170)
Bug in setitem where type promotion is applied to the entire block (GH10280)
Bug in Series arithmetic methods may incorrectly hold names (GH10068)
Bug in GroupBy.get_group when grouping on multiple keys, one of which is categorical. (GH10132)
Bug in DatetimeIndex and TimedeltaIndex names are lost after timedelta arithmetics ( GH9926)
Bug in DataFrame construction from nested dict with datetime64 (GH10160)
Bug in Series construction from dict with datetime64 keys (GH9456)
Bug in Series.plot(label="LABEL") not correctly setting the label (GH10119)
Bug in plot not defaulting to matplotlib axes.grid setting (GH9792)
Bug causing strings containing an exponent, but no decimal to be parsed as int instead of float in
engine=python for the read_csv parser (GH9565)
Bug in Series.align resets name when fill_value is specified (GH10067)
Bug in read_csv causing index name not to be set on an empty DataFrame (GH10184)
Bug in SparseSeries.abs resets name (GH10241)
Bug in TimedeltaIndex slicing may reset freq (GH10292)
Bug in GroupBy.get_group raises ValueError when group key contains NaT (GH6992)
Bug in SparseSeries constructor ignores input data name (GH10258)
Bug in Categorical.remove_categories causing a ValueError when removing the NaN category
if underlying dtype is floating-point (GH10156)
Bug where infer_freq infers timerule (WOM-5XXX) unsupported by to_offset (GH9425)
Bug in DataFrame.to_hdf() where table format would raise a seemingly unrelated error for invalid (nonstring) column names. This is now explicitly forbidden. (GH9057)
Bug to handle masking empty DataFrame (GH10126).
Bug where MySQL interface could not handle numeric table/column names (GH10255)
Bug in read_csv with a date_parser that returned a datetime64 array of other time resolution than
[ns] (GH10245)
Bug in Panel.apply when the result has ndim=0 (GH10332)
Bug in read_hdf where auto_close could not be passed (GH9327).
Bug in read_hdf where open stores could not be used (GH10330).
31
Bug in adding empty DataFrames, now results in a DataFrame that .equals an empty
DataFrame (GH10181).
Bug in to_hdf and HDFStore which did not check that complib choices were valid (GH4582, GH8874).
1.3.1 Enhancements
CategoricalIndex
We introduce a CategoricalIndex, a new type of index object that is useful for supporting indexing with duplicates. This is a container around a Categorical (introduced in v0.15.0) and allows efficient indexing and storage
of an index with a large number of duplicated elements. Prior to 0.16.1, setting the index of a DataFrame/Series
with a category dtype would convert this to regular object-based Index.
32
In [6]: df2.index
Out[6]: CategoricalIndex([u'a', u'a', u'b', u'b', u'c', u'a'], categories=[u'c', u'a', u'b'], ordered
indexing with __getitem__/.iloc/.loc/.ix works similarly to an Index with duplicates. The indexers
MUST be in the category or the operation will raise.
In [7]: df2.loc['a']
Out[7]:
A
B
a 0
a 1
a 5
In [8]: df2.loc['a'].index
Out[8]: CategoricalIndex([u'a', u'a', u'a'], categories=[u'c', u'a', u'b'], ordered=False, name=u'B',
33
groupby operations on the index will preserve the index nature as well
In [10]: df2.groupby(level=0).sum()
Out[10]:
A
B
c 4
a 6
b 5
In [11]: df2.groupby(level=0).sum().index
Out[11]: CategoricalIndex([u'c', u'a', u'b'], categories=[u'c', u'a', u'b'], ordered=False, name=u'B'
reindexing operations, will return a resulting index based on the type of the passed indexer, meaning that passing a
list will return a plain-old-Index; indexing with a Categorical will return a CategoricalIndex, indexed
according to the categories of the PASSED Categorical dtype. This allows one to arbitrarly index these even with
values NOT in the categories, similarly to how you can reindex ANY pandas index.
In [12]: df2.reindex(['a','e'])
Out[12]:
A
B
a
0
a
1
a
5
e NaN
In [13]: df2.reindex(['a','e']).index
Out[13]: Index([u'a', u'a', u'a', u'e'], dtype='object', name=u'B')
In [14]: df2.reindex(pd.Categorical(['a','e'],categories=list('abcde')))
Out[14]:
A
B
a
0
a
1
a
5
e NaN
In [15]: df2.reindex(pd.Categorical(['a','e'],categories=list('abcde'))).index
Out[15]: CategoricalIndex([u'a', u'a', u'a', u'e'], categories=[u'a', u'e'], ordered=False, name=u'B'
34
When applied to a DataFrame, one may pass the name of a column to specify sampling weights when sampling from
rows.
In [24]: df = DataFrame({'col1':[9,8,7,6], 'weight_column':[0.5, 0.4, 0.1, 0]})
In [25]: df.sample(n=3, weights='weight_column')
Out[25]:
col1 weight_column
1
8
0.4
0
9
0.5
2
7
0.1
35
In [26]: idx = Index([' jack', 'jill ', ' jesse ', 'frank'])
In [27]: idx.str.strip()
Out[27]: Index([u'jack', u'jill', u'jesse', u'frank'], dtype='object')
One special case for the .str accessor on Index is that if a string method returns bool, the .str accessor
will return a np.array instead of a boolean Index (GH8875). This enables the following expression to work
naturally:
In [28]: idx = Index(['a1', 'a2', 'b1', 'b2'])
In [29]: s = Series(range(4), index=idx)
In [30]: s
Out[30]:
a1
0
a2
1
b1
2
b2
3
dtype: int64
In [31]: idx.str.startswith('a')
Out[31]: array([ True, True, False, False], dtype=bool)
In [32]: s[s.index.str.startswith('a')]
Out[32]:
a1
0
a2
1
dtype: int64
The following new methods are accesible via .str accessor to apply the function to each values. (GH9766,
GH9773, GH10031, GH10045, GH10052)
capitalize()
index()
swapcase()
rindex()
Methods
normalize()
translate()
partition()
rpartition()
split now takes expand keyword to specify whether to expand dimensionality. return_type is deprecated. (GH9847)
In [33]: s = Series(['a,b', 'a,c', 'b,c'])
# return Series
In [34]: s.str.split(',')
Out[34]:
0
[a, b]
1
[a, c]
2
[b, c]
dtype: object
# return DataFrame
In [35]: s.str.split(',', expand=True)
Out[35]:
0 1
0 a b
1 a c
2 b c
In [36]: idx = Index(['a,b', 'a,c', 'b,c'])
36
# return Index
In [37]: idx.str.split(',')
Out[37]: Index([[u'a', u'b'], [u'a', u'c'], [u'b', u'c']], dtype='object')
# return MultiIndex
In [38]: idx.str.split(',', expand=True)
Out[38]:
MultiIndex(levels=[[u'a', u'b'], [u'b', u'c']],
labels=[[0, 0, 1], [0, 1, 1]])
DataFrame.diff now takes an axis parameter that determines the direction of differencing (GH9727)
Allow clip, clip_lower, and clip_upper to accept array-like arguments as thresholds (This is a regression from 0.11.0). These methods now have an axis parameter which determines how the Series or DataFrame
will be aligned with the threshold(s). (GH6966)
DataFrame.mask() and Series.mask() now support same keywords as where (GH8801)
drop function can now accept errors keyword to suppress ValueError raised when any of label does not
exist in the target data. (GH6736)
In [43]: df = DataFrame(np.random.randn(3, 3), columns=['A', 'B', 'C'])
In [44]: df.drop(['A', 'X'], axis=1, errors='ignore')
Out[44]:
B
C
0 0.991946 0.953324
1 -0.334077 0.002118
2 0.289092 1.321158
Add support for separating years and quarters using dashes, for example 2014-Q1. (GH9688)
Allow conversion of values with dtype datetime64 or timedelta64 to strings using astype(str)
(GH9757)
get_dummies function now accepts sparse keyword. If set to True, the return DataFrame is sparse, e.g.
SparseDataFrame. (GH8823)
Period now accepts datetime64 as value input. (GH9054)
Allow timedelta string conversion when leading zero is missing from time definition, ie 0:00:00 vs 00:00:00.
(GH9570)
1.3. v0.16.1 (May 11, 2015)
37
In [3]: pd.Index(range(104),name='foo')
Out[3]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
In [4]: pd.date_range('20130101',periods=4,name='foo',tz='US/Eastern')
Out[4]:
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-01-01 00:00:00-05:00, ..., 2013-01-04 00:00:00-05:00]
Length: 4, Freq: D, Timezone: US/Eastern
In [5]: pd.date_range('20130101',periods=104,name='foo',tz='US/Eastern')
Out[5]:
38
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-01-01 00:00:00-05:00, ..., 2013-04-14 00:00:00-04:00]
Length: 104, Freq: D, Timezone: US/Eastern
New Behavior
In [45]: pd.set_option('display.width', 80)
In [46]: pd.Index(range(4), name='foo')
Out[46]: Int64Index([0, 1, 2, 3], dtype='int64', name=u'foo')
In [47]: pd.Index(range(30), name='foo')
Out[47]:
Int64Index([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
dtype='int64', name=u'foo')
In [48]: pd.Index(range(104), name='foo')
Out[48]:
Int64Index([ 0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
...
94, 95, 96, 97, 98, 99, 100, 101, 102, 103],
dtype='int64', name=u'foo', length=104)
In [49]: pd.CategoricalIndex(['a','bb','ccc','dddd'], ordered=True, name='foobar')
Out[49]: CategoricalIndex([u'a', u'bb', u'ccc', u'dddd'], categories=[u'a', u'bb', u'ccc', u'dddd'],
'2013-01-04',
'2013-01-08',
'2013-01-12',
'2013-01-16',
'2013-01-20',
39
40
41
Bug in which groupby.transform incorrectly enforced output dtypes to match input dtypes. (GH9807)
Bug in DataFrame constructor when columns parameter is set, and data is an empty list (GH9939)
Bug in bar plot with log=True raises TypeError if all values are less than 1 (GH9905)
Bug in horizontal bar plot ignores log=True (GH9905)
Bug in PyTables queries that did not return proper results using the index (GH8265, GH9676)
Bug where dividing a dataframe containing values of type Decimal by another Decimal would raise.
(GH9787)
Bug where using DataFrames asfreq would remove the name of the index. (GH9885)
Bug causing extra index point when resample BM/BQ (GH9756)
Changed caching in AbstractHolidayCalendar to be at the instance level rather than at the class level as
the latter can result in unexpected behaviour. (GH9552)
Fixed latex output for multi-indexed dataframes (GH9778)
Bug causing an exception when setting an empty range using DataFrame.loc (GH9596)
Bug in hiding ticklabels with subplots and shared axes when adding a new plot to an existing grid of axes
(GH9158)
Bug in transform and filter when grouping on a categorical variable (GH9921)
Bug in transform when groups are equal in number and dtype to the input index (GH9700)
Google BigQuery connector now imports dependencies on a per-method basis.(GH9713)
Updated BigQuery connector to no longer use deprecated oauth2client.tools.run() (GH8327)
Bug in subclassed DataFrame. It may not return the correct class, when slicing or subsetting it. (GH9632)
Bug in .median() where non-float null values are not handled correctly (GH10040)
Bug in Series.fillna() where it raises if a numerically convertible string is given (GH10092)
to
Timedelta
to
conform
the
.seconds
attribute
with
Changes to the .loc slicing API to conform with the behavior of .ix see here
Changes to the default for ordering in the Categorical constructor, see here
Enhancement to the .str accessor to make string operations easier, see here
The pandas.tools.rplot, pandas.sandbox.qtpandas and pandas.rpy modules are deprecated.
We refer users to external packages like seaborn, pandas-qt and rpy2 for similar or equivalent functionality, see
here
42
PetalLength
1.4
1.4
1.3
1.5
1.4
PetalWidth
0.2
0.2
0.2
0.2
0.2
In [3]: iris.assign(sepal_ratio=iris['SepalWidth'] /
Out[3]:
SepalLength SepalWidth PetalLength PetalWidth
0
5.1
3.5
1.4
0.2
1
4.9
3.0
1.4
0.2
2
4.7
3.2
1.3
0.2
3
4.6
3.1
1.5
0.2
4
5.0
3.6
1.4
0.2
Name
Iris-setosa
Iris-setosa
Iris-setosa
Iris-setosa
Iris-setosa
iris['SepalLength']).head()
Name
Iris-setosa
Iris-setosa
Iris-setosa
Iris-setosa
Iris-setosa
sepal_ratio
0.686275
0.612245
0.680851
0.673913
0.720000
Above was an example of inserting a precomputed value. We can also pass in a function to be evalutated.
In [4]: iris.assign(sepal_ratio = lambda x: (x['SepalWidth'] /
...:
x['SepalLength'])).head()
...:
Out[4]:
SepalLength SepalWidth PetalLength PetalWidth
Name sepal_ratio
43
0
1
2
3
4
5.1
4.9
4.7
4.6
5.0
3.5
3.0
3.2
3.1
3.6
1.4
1.4
1.3
1.5
1.4
0.2
0.2
0.2
0.2
0.2
Iris-setosa
Iris-setosa
Iris-setosa
Iris-setosa
Iris-setosa
0.686275
0.612245
0.680851
0.673913
0.720000
The power of assign comes when used in chains of operations. For example, we can limit the DataFrame to just
those with a Sepal Length greater than 5, calculate the ratio, and plot
In [5]: (iris.query('SepalLength > 5')
...:
.assign(SepalRatio = lambda x: x.SepalWidth / x.SepalLength,
...:
PetalRatio = lambda x: x.PetalWidth / x.PetalLength)
...:
.plot(kind='scatter', x='SepalRatio', y='PetalRatio'))
...:
Out[5]: <matplotlib.axes._subplots.AxesSubplot at 0xa993cbcc>
44
1
NaN
0
1
1
3
2 1 b 0
NaN
1
NaN
dtype: float64
1
# SparseSeries
In [10]: ss = s.to_sparse()
In [11]: ss
Out[11]:
A B C D
1 2 a 0
3
1
NaN
1 b 0
1
1
3
2 1 b 0
NaN
1
NaN
dtype: float64
BlockIndex
Block locations: array([0, 2])
Block lengths: array([1, 2])
In [12]: A, rows, columns = ss.to_coo(row_levels=['A', 'B'],
....:
column_levels=['C', 'D'],
....:
sort_labels=False)
....:
In [13]: A
Out[13]:
<3x4 sparse matrix of type '<type 'numpy.float64'>'
with 3 stored elements in COOrdinate format>
In [14]: A.todense()
Out[14]:
matrix([[ 3., 0., 0.,
[ 0., 0., 1.,
[ 0., 0., 0.,
0.],
3.],
0.]])
In [15]: rows
Out[15]: [(1L, 2L), (1L, 1L), (2L, 1L)]
In [16]: columns
Out[16]: [('a', 0L), ('a', 1L), ('b', 0L), ('b', 1L)]
convenience
method
for
creating
SparseSeries
from
45
2.],
0.],
0.]])
In [21]: ss = SparseSeries.from_coo(A)
In [22]: ss
Out[22]:
0 2
1
3
2
1 0
3
dtype: float64
BlockIndex
Block locations: array([0])
Block lengths: array([3])
isalpha()
isupper()
rfind()
Methods
isdigit()
istitle()
ljust()
isdigit()
isnumeric()
rjust()
isspace()
isdecimal()
zfill()
Series.str.pad() and Series.str.center() now accept fillchar option to specify filling character (GH9352)
In [26]: s = Series(['12', '300', '25'])
In [27]: s.str.pad(5, fillchar='_')
Out[27]:
0
___12
1
__300
2
___25
dtype: object
46
Other enhancements
Reindex now supports method=nearest for frames or series with a monotonic increasing or decreasing
index (GH9258):
In [31]: df = pd.DataFrame({'x': range(5)})
In [32]: df.reindex([0.2, 1.8, 3.5], method='nearest')
Out[32]:
x
0.2 0
1.8 2
3.5 4
This method is also exposed by the lower level Index.get_indexer and Index.get_loc methods.
The read_excel() functions sheetname argument now accepts a list and None, to get multiple or all sheets
respectively. If more than one sheet is specified, a dictionary is returned. (GH9450)
# Returns the 1st and 4th sheet, as a dictionary of DataFrames.
pd.read_excel('path_to_file.xls',sheetname=['Sheet1',3])
Allow Stata files to be read incrementally with an iterator; support for long strings in Stata files. See the docs
here (GH9493:).
Paths beginning with ~ will now be expanded to begin with the users home directory (GH9066)
Added time interval selection in get_data_yahoo (GH9071)
Added Timestamp.to_datetime64() to complement Timedelta.to_timedelta64() (GH9255)
tseries.frequencies.to_offset() now accepts Timedelta as input (GH9064)
Lag parameter was added to the autocorrelation method of Series, defaults to lag-1 autocorrelation (GH9192)
Timedelta will now accept nanoseconds keyword in constructor (GH9273)
SQL code now safely escapes table and column names (GH8986)
Added auto-complete for Series.str.<tab>, Series.dt.<tab> and Series.cat.<tab>
(GH9322)
47
Index.get_indexer now supports method=pad and method=backfill even for any target array, not just monotonic targets. These methods also work for monotonic decreasing as well as monotonic
increasing indexes (GH9258).
Index.asof now works on all index types (GH9258).
A verbose argument has been augmented in io.read_excel(), defaults to False. Set to True to print
sheet names as they are parsed. (GH9450)
Added days_in_month (compatibility alias daysinmonth) property to Timestamp, DatetimeIndex,
Period, PeriodIndex, and Series.dt (GH9572)
Added decimal option in to_csv to provide formatting for non-. decimal separators (GH781)
Added normalize option for Timestamp to normalized to midnight (GH8794)
Added example for DataFrame import to R using HDF5 file and rhdf5 library. See the documentation for
more (GH9636).
New Behavior
In [33]: t = pd.Timedelta('1 day, 10:11:12.100123')
In [34]: t.days
Out[34]: 1L
In [35]: t.seconds
Out[35]: 36672L
In [36]: t.microseconds
Out[36]: 100123L
48
In [37]: t.components
Out[37]: Components(days=1L, hours=10L, minutes=11L, seconds=12L, milliseconds=100L, microseconds=123
In [38]: t.components.seconds
Out[38]: 12L
Indexing Changes
The behavior of a small sub-set of edge cases for using .loc have changed (GH8613). Furthermore we have improved
the content of the error messages that are raised:
Slicing with .loc where the start and/or stop bound is not found in the index is now allowed; this previously
would raise a KeyError. This makes the behavior the same as .ix in this case. This change is only for
slicing, not when indexing with a single label.
In [39]: df = DataFrame(np.random.randn(5,4),
....:
columns=list('ABCD'),
....:
index=date_range('20130101',periods=5))
....:
In [40]: df
Out[40]:
A
B
C
D
2013-01-01 -1.546906 -0.202646 -0.655969 0.193421
2013-01-02 0.553439 1.318152 -0.469305 0.675554
2013-01-03 -1.817027 -0.183109 1.058969 -0.397840
2013-01-04 0.337438 1.047579 1.045938 0.863717
2013-01-05 -0.122092 0.124713 -0.322795 0.841675
In [41]: s = Series(range(5),[-2,-1,1,2,3])
In [42]: s
Out[42]:
-2
0
-1
1
1
2
2
3
3
4
dtype: int64
Previous Behavior
In [4]: df.loc['2013-01-02':'2013-01-10']
KeyError: 'stop bound [2013-01-10] is not in the [index]'
In [6]: s.loc[-10:3]
KeyError: 'start bound [-10] is not the [index]'
New Behavior
In [43]: df.loc['2013-01-02':'2013-01-10']
Out[43]:
A
B
C
D
2013-01-02 0.553439 1.318152 -0.469305 0.675554
2013-01-03 -1.817027 -0.183109 1.058969 -0.397840
2013-01-04 0.337438 1.047579 1.045938 0.863717
49
2013-01-05 -0.122092
0.124713 -0.322795
0.841675
In [44]: s.loc[-10:3]
Out[44]:
-2
0
-1
1
1
2
2
3
3
4
dtype: int64
Allow slicing with float-like values on an integer index for .ix. Previously this was only enabled for .loc:
Previous Behavior
In [8]: s.ix[-1.0:2]
TypeError: the slice start value [-1.0] is not a proper indexer for this index type (Int64Index)
New Behavior
In [45]: s.ix[-1.0:2]
Out[45]:
-1
1
1
2
2
3
dtype: int64
Provide a useful exception for indexing with an invalid type for that index when using .loc. For example
trying to use .loc on an index of type DatetimeIndex or PeriodIndex or TimedeltaIndex, with an
integer (or a float).
Previous Behavior
In [4]: df.loc[2:3]
KeyError: 'start bound [2] is not the [index]'
New Behavior
In [4]: df.loc[2:3]
TypeError: Cannot do slice indexing on <class 'pandas.tseries.index.DatetimeIndex'> with <type '
Categorical Changes
In prior versions, Categoricals that had an unspecified ordering (meaning no ordered keyword was passed)
were defaulted as ordered Categoricals. Going forward, the ordered keyword in the Categorical constructor
will default to False. Ordering must now be explicit.
Furthermore, previously you could change the ordered attribute of a Categorical by just setting the attribute, e.g. cat.ordered=True; This is now deprecated and you should use cat.as_ordered() or
cat.as_unordered(). These will by default return a new object and not modify the existing object. (GH9347,
GH9190)
Previous Behavior
In [3]: s = Series([0,1,2], dtype='category')
In [4]: s
Out[4]:
0
0
50
1
1
2
2
dtype: category
Categories (3, int64): [0 < 1 < 2]
In [5]: s.cat.ordered
Out[5]: True
In [6]: s.cat.ordered = False
In [7]: s
Out[7]:
0
0
1
1
2
2
dtype: category
Categories (3, int64): [0, 1, 2]
New Behavior
In [46]: s = Series([0,1,2], dtype='category')
In [47]: s
Out[47]:
0
0
1
1
2
2
dtype: category
Categories (3, int64): [0, 1, 2]
In [48]: s.cat.ordered
Out[48]: False
In [49]: s = s.cat.as_ordered()
In [50]: s
Out[50]:
0
0
1
1
2
2
dtype: category
Categories (3, int64): [0 < 1 < 2]
In [51]: s.cat.ordered
Out[51]: True
# you can set in the constructor of the Categorical
In [52]: s = Series(Categorical([0,1,2],ordered=True))
In [53]: s
Out[53]:
0
0
1
1
2
2
dtype: category
Categories (3, int64): [0 < 1 < 2]
In [54]: s.cat.ordered
51
Out[54]: True
For ease of creation of series of categorical data, we have added the ability to pass keywords when calling
.astype(). These are passed directly to the constructor.
In [55]: s = Series(["a","b","c","a"]).astype('category',ordered=True)
In [56]: s
Out[56]:
0
a
1
b
2
c
3
a
dtype: category
Categories (3, object): [a < b < c]
In [57]: s = Series(["a","b","c","a"]).astype('category',categories=list('abcdef'),ordered=False)
In [58]: s
Out[58]:
0
a
1
b
2
c
3
a
dtype: category
Categories (6, object): [a, b, c, d, e, f]
52
Series now supports bitwise operation for integral types (GH9016). Previously even if the input dtypes were
integral, the output dtype was coerced to bool.
Previous Behavior
In [2]: pd.Series([0,1,2,3], list('abcd')) | pd.Series([4,4,4,4], list('abcd'))
Out[2]:
a
True
b
True
c
True
d
True
dtype: bool
New Behavior. If the input dtypes are integral, the output dtype is also integral and the output values are the
result of the bitwise operation.
In [2]: pd.Series([0,1,2,3], list('abcd')) | pd.Series([4,4,4,4], list('abcd'))
Out[2]:
a
4
b
5
c
6
d
7
dtype: int64
During division involving a Series or DataFrame, 0/0 and 0//0 now give np.nan instead of np.inf.
(GH9144, GH8445)
Previous Behavior
In [2]: p = pd.Series([0, 1])
In [3]: p / 0
Out[3]:
0
inf
1
inf
dtype: float64
In [4]: p // 0
Out[4]:
0
inf
1
inf
dtype: float64
New Behavior
In [59]: p = pd.Series([0, 1])
In [60]: p / 0
Out[60]:
0
NaN
1
inf
dtype: float64
In [61]: p // 0
Out[61]:
0
NaN
1
inf
dtype: float64
Series.values_counts and Series.describe for categorical data will now put NaN entries at the
53
end. (GH9443)
Series.describe for categorical data will now give counts and frequencies of 0, not NaN, for unused
categories (GH9443)
Due to a bug fix, looking up a partial string label with DatetimeIndex.asof now includes values that
match the string, even if they are after the start of the partial string label (GH9258).
Old behavior:
In [4]: pd.to_datetime(['2000-01-31', '2000-02-28']).asof('2000-02')
Out[4]: Timestamp('2000-01-31 00:00:00')
Fixed behavior:
In [62]: pd.to_datetime(['2000-01-31', '2000-02-28']).asof('2000-02')
Out[62]: Timestamp('2000-02-28 00:00:00')
To reproduce the old behavior, simply add more precision to the label (e.g., use 2000-02-01 instead of
2000-02).
Deprecations
The rplot trellis plotting interface is deprecated and will be removed in a future version. We refer to external
packages like seaborn for similar but more refined functionality (GH3445). The documentation includes some
examples how to convert your existing code using rplot to seaborn: rplot docs.
The pandas.sandbox.qtpandas interface is deprecated and will be removed in a future version. We refer
users to the external package pandas-qt. (GH9615)
The pandas.rpy interface is deprecated and will be removed in a future version. Similar functionaility can
be accessed thru the rpy2 project (GH9602)
Adding DatetimeIndex/PeriodIndex to another DatetimeIndex/PeriodIndex is being deprecated as a set-operation. This will be changed to a TypeError in a future version. .union() should be used
for the union set operation. (GH9094)
Subtracting DatetimeIndex/PeriodIndex from another DatetimeIndex/PeriodIndex is being deprecated as a set-operation. This will be changed to an actual numeric subtraction yielding a
TimeDeltaIndex in a future version. .difference() should be used for the differencing set operation.
(GH9094)
Removal of prior version deprecations/changes
DataFrame.pivot_table and crosstabs rows and cols keyword arguments were removed in favor
of index and columns (GH6581)
DataFrame.to_excel and DataFrame.to_csv cols keyword argument was removed in favor of
columns (GH6581)
Removed convert_dummies in favor of get_dummies (GH6581)
Removed value_range in favor of describe (GH6581)
55
56
Fix bug in DataFrame.Groupby where sort=False is ignored in the case of Categorical columns.
(GH8868)
Fixed bug with reading CSV files from Amazon S3 on python 3 raising a TypeError (GH9452)
Bug in the Google BigQuery reader where the jobComplete key may be present but False in the query results
(GH8728)
Bug in Series.values_counts with excluding NaN for categorical type Series with dropna=True
(GH9443)
Fixed mising numeric_only option for DataFrame.std/var/sem (GH9201)
Support constructing Panel or Panel4D with scalar data (GH8285)
Series text representation disconnected from max_rows/max_columns (GH7508).
Series number formatting inconsistent when truncated (GH8532).
Previous Behavior
In [2]: pd.options.display.max_rows = 10
In [3]: s = pd.Series([1,1,1,1,1,1,1,1,1,1,0.9999,1,1]*10)
In [4]: s
Out[4]:
0
1
1
1
2
1
...
127
0.9999
128
1.0000
129
1.0000
Length: 130, dtype: float64
New Behavior
0
1
2
3
4
...
125
126
127
128
129
dtype:
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
0.9999
1.0000
1.0000
float64
A Spurious SettingWithCopy Warning was generated when setting a new item in a frame in some cases
(GH8730)
The following would previously report a SettingWithCopy Warning.
In [1]: df1 = DataFrame({'x': Series(['a','b','c']), 'y': Series(['d','e','f'])})
In [2]: df2 = df1[['x']]
In [3]: df2['y'] = ['g', 'h', 'i']
57
0.043324
0.561433
0.329668
0.502967
In [3]: df.index.lexsort_depth
Out[3]: 1
# in prior versions this would raise a KeyError
# will now show a PerformanceWarning
In [4]: df.loc[(1, 'z')]
Out[4]:
jolie
jim joe
1
z
0.329668
# lexically sorting
In [5]: df2 = df.sortlevel()
In [6]: df2
Out[6]:
jolie
jim joe
0
x
x
1
y
z
0.043324
0.561433
0.502967
0.329668
In [7]: df2.index.lexsort_depth
Out[7]: 2
58
In [8]: df2.loc[(1,'z')]
Out[8]:
jolie
jim joe
1
z
0.329668
Bug in unique of Series with category dtype, which returned all categories regardless whether they were
used or not (see GH8559 for the discussion). Previous behaviour was to return all categories:
In [3]: cat = pd.Categorical(['a', 'b', 'a'], categories=['a', 'b', 'c'])
In [4]: cat
Out[4]:
[a, b, a]
Categories (3, object): [a < b < c]
In [5]: cat.unique()
Out[5]: array(['a', 'b', 'c'], dtype=object)
Now, only the categories that do effectively occur in the array are returned:
In [9]: cat = pd.Categorical(['a', 'b', 'a'], categories=['a', 'b', 'c'])
In [10]: cat.unique()
Out[10]:
[a, b]
Categories (2, object): [a, b]
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. (GH8302).
Allow equality comparisons of Series with a categorical dtype and object dtype; previously these would raise
TypeError (GH8938)
Bug in NDFrame: conflicting attribute/column names now behave consistently between getting and setting.
Previously, when both a column and attribute named y existed, data.y would return the attribute, while
data.y = z would update the column (GH8994)
In [11]: data = pd.DataFrame({'x':[1, 2, 3]})
In [12]: data.y = 2
In [13]: data['y'] = [2, 4, 6]
In [14]: data
Out[14]:
x y
0 1 2
1 2 4
2 3 6
# this assignment was inconsistent
In [15]: data.y = 5
Old behavior:
59
In [6]: data.y
Out[6]: 2
In [7]: data['y'].values
Out[7]: array([5, 5, 5])
New behavior:
In [16]: data.y
Out[16]: 5
In [17]: data['y'].values
Out[17]: array([2, 4, 6], dtype=int64)
Timestamp(now) is now equivalent to Timestamp.now() in that it returns the local time rather than
UTC. Also, Timestamp(today) is now equivalent to Timestamp.today() and both have tz as a
possible argument. (GH9000)
Fix negative step support for label-based slices (GH8753)
Old behavior:
In [1]: s = pd.Series(np.arange(3), ['a', 'b', 'c'])
Out[1]:
a
0
b
1
c
2
dtype: int64
In [2]: s.loc['c':'a':-1]
Out[2]:
c
2
dtype: int64
New behavior:
In [18]: s = pd.Series(np.arange(3), ['a', 'b', 'c'])
In [19]: s.loc['c':'a':-1]
Out[19]:
c
2
b
1
a
0
dtype: int32
1.5.2 Enhancements
Categorical enhancements:
Added ability to export Categorical data to Stata (GH8633). See here for limitations of categorical variables
exported to Stata data files.
Added flag order_categoricals to StataReader and read_stata to select whether to order imported categorical data (GH8836). See here for more information on importing categorical variables from Stata
data files.
Added ability to export Categorical data to to/from HDF5 (GH7621). Queries work the same as if it was an
object array. However, the category dtyped data is stored in a more efficient manner. See here for an
example and caveats w.r.t. prior versions of pandas.
60
Series.all and Series.any now support the level and skipna parameters (GH8302):
In [20]: s = pd.Series([False, True, False], index=[0, 0, 1])
In [21]: s.any(level=0)
Out[21]:
0
True
1
False
dtype: bool
Panel now supports the all and any aggregation functions. (GH8302):
In [22]: p = pd.Panel(np.random.rand(2, 5, 4) > 0.1)
In [23]: p.all()
Out[23]:
0
1
0
True False
1
True
True
2
True
True
3 False
True
61
1.5.3 Performance
Reduce memory usage when skiprows is an integer in read_csv (GH8681)
Performance boost for to_datetime conversions with a passed format=, and the exact=False
(GH8904)
62
Imported categorical variables from Stata files retain the ordinal information in the underlying data (GH8836).
Defined .size attribute across NDFrame objects to provide compat with numpy >= 1.9.1; buggy with
np.array_split (GH8846)
Skip testing of histogram plots for matplotlib <= 1.2 (GH8648).
Bug where get_data_google returned object dtypes (GH3995)
Bug in DataFrame.stack(..., dropna=False) when the DataFrames columns is a MultiIndex
whose labels do not reference all its levels. (GH8844)
Bug in that Option context applied on __enter__ (GH8514)
Bug in resample that causes a ValueError when resampling across multiple days and the last offset is not calculated from the start of the range (GH8683)
Bug where DataFrame.plot(kind=scatter) fails when checking if an np.array is in the DataFrame
(GH8852)
Bug in pd.infer_freq/DataFrame.inferred_freq that prevented proper sub-daily frequency inference when the index contained DST days (GH8772).
Bug where index name was still used when plotting a series with use_index=False (GH8558).
Bugs when trying to stack multiple columns, when some (or all) of the level names are numbers (GH8584).
Bug in MultiIndex where __contains__ returns wrong result if index is not lexically sorted or unique
(GH7724)
BUG CSV: fix problem with trailing whitespace in skipped rows, (GH8679), (GH8661), (GH8983)
Regression in Timestamp does not parse Z zone designator for UTC (GH8771)
Bug in StataWriter the produces writes strings with 244 characters irrespective of actual size (GH8969)
Fixed ValueError raised by cummin/cummax when datetime64 Series contains NaT. (GH8965)
Bug in Datareader returns object dtype if there are missing values (GH8980)
Bug in plotting if sharex was enabled and index was a timeseries, would show labels on multiple axes (GH3964).
Bug where passing a unit to the TimedeltaIndex constructor applied the to nano-second conversion twice.
(GH9011).
Bug in plotting of a period-like array (GH9012)
63
previous behavior:
In [6]: s.dt.hour
Out[6]:
0
0
1
0
2
-1
3
0
4
0
dtype: int64
current behavior:
In [4]: s.dt.hour
Out[4]:
0
0
1
0
2
NaN
3
0
4
0
dtype: float64
groupby with as_index=False will not add erroneous extra columns to result (GH8582):
In [5]: np.random.seed(2718281)
In [6]: df = pd.DataFrame(np.random.randint(0, 100, (10, 2)),
...:
columns=['jim', 'joe'])
...:
In [7]: df.head()
Out[7]:
jim joe
0
61
81
1
96
49
2
55
65
3
72
51
4
77
12
In [8]: ts = pd.Series(5 * np.random.randint(0, 3, 10))
previous behavior:
64
current behavior:
In [9]: df.groupby(ts, as_index=False).max()
Out[9]:
jim joe
0
72
83
1
77
84
2
96
65
groupby will not erroneously exclude columns if the column name conflics with the grouper name (GH8112):
In [10]: df = pd.DataFrame({'jim': range(5), 'joe': range(5, 10)})
In [11]: df
Out[11]:
jim joe
0
0
5
1
1
6
2
2
7
3
3
8
4
4
9
In [12]: gr = df.groupby(df['jim'] < 2)
current behavior:
In [13]: gr.apply(sum)
Out[13]:
jim joe
jim
False
9
24
True
1
11
Support for slicing with monotonic decreasing indexes, even if start or stop is not found in the index
(GH7860):
In [14]: s = pd.Series(['a', 'b', 'c', 'd'], [4, 3, 2, 1])
In [15]: s
Out[15]:
4
a
3
b
2
c
65
1
d
dtype: object
previous behavior:
In [8]: s.loc[3.5:1.5]
KeyError: 3.5
current behavior:
In [16]: s.loc[3.5:1.5]
Out[16]:
3
b
2
c
dtype: object
io.data.Options has been fixed for a change in the format of the Yahoo Options page (GH8612),
(GH8741)
Note: As a result of a change in Yahoos option page layout, when an expiry date is given, Options methods
now return data for a single expiry date. Previously, methods returned all data for the selected month.
The month and year parameters have been undeprecated and can be used to get all options data for a given
month.
If an expiry date that is not valid is given, data for the next expiry after the given date is returned.
Option data frames are now saved on the instance as callsYYMMDD or putsYYMMDD. Previously they were
saved as callsMMYY and putsMMYY. The next expiry is saved as calls and puts.
New features:
The expiry parameter can now be a single date or a list-like object containing dates.
A new property expiry_dates was added, which returns all available expiry dates.
Current behavior:
In [17]: from pandas.io.data import Options
In [18]: aapl = Options('aapl','yahoo')
In [19]: aapl.get_call_data().iloc[0:5,0:1]
Out[19]:
Last
Strike
60
65
70
75
79
Expiry
2015-10-16
2015-10-16
2015-10-16
2015-10-16
2015-10-16
Type
call
call
call
call
call
Symbol
AAPL151016C00060000
AAPL151016C00065000
AAPL151016C00070000
AAPL151016C00075000
AAPL151016C00079000
51.00
47.84
38.68
36.65
30.80
In [20]: aapl.expiry_dates
Out[20]:
[datetime.date(2015, 10, 16),
datetime.date(2015, 10, 23),
datetime.date(2015, 10, 30),
datetime.date(2015, 11, 6),
datetime.date(2015, 11, 13),
datetime.date(2015, 11, 20),
66
datetime.date(2015,
datetime.date(2016,
datetime.date(2016,
datetime.date(2016,
datetime.date(2016,
datetime.date(2017,
datetime.date(2018,
12, 18),
1, 15),
4, 15),
6, 17),
7, 15),
1, 20),
1, 19)]
In [21]: aapl.get_near_stock_price(expiry=aapl.expiry_dates[0:3]).iloc[0:5,0:1]
Out[21]:
Last
Strike Expiry
Type Symbol
111
2015-10-23 call AAPL151023C00111000 2.44
2015-10-30 call AAPL151030C00111000 4.45
112
2015-10-16 call AAPL151016C00112000 1.13
2015-10-23 call AAPL151023C00112000 1.85
2015-10-30 call AAPL151030C00112000 3.85
1.6.2 Enhancements
concat permits a wider variety of iterables of pandas objects to be passed as the first parameter (GH8645):
In [22]: from collections import deque
In [23]: df1 = pd.DataFrame([1, 2, 3])
In [24]: df2 = pd.DataFrame([4, 5, 6])
previous behavior:
current behavior:
In [25]: pd.concat(deque((df1, df2)))
Out[25]:
0
0 1
1 2
2 3
0 4
1 5
2 6
Represent MultiIndex labels with a dtype that utilizes memory based on the level size. In prior versions,
the memory usage was a constant 8 bytes per element in each level. In addition, in prior versions, the reported
memory usage was incorrect as it didnt show the usage for the memory occupied by the underling data array.
(GH8456)
67
previous behavior:
# this was underreported in prior versions
In [1]: dfi.memory_usage(index=True)
Out[1]:
Index
8000 # took about 24008 bytes in < 0.15.1
A
8000
dtype: int64
current behavior:
In [27]: dfi.memory_usage(index=True)
Out[27]:
Index
11020
A
8000
dtype: int64
68
Bug in Categorical reflected comparison operator raising if the first argument was a numpy array scalar
(e.g. np.int64) (GH8658)
Bug in Panel indexing with a list-like (GH8710)
Compat issue is DataFrame.dtypes when options.mode.use_inf_as_null is True (GH8722)
Bug in read_csv, dialect parameter would not take a string (:issue: 8703)
Bug in slicing a multi-index level with an empty-list (GH8737)
Bug in numeric index operations of add/sub with Float/Index Index with numpy arrays (GH8608)
Bug in setitem with empty indexer and unwanted coercion of dtypes (GH8669)
Bug in ix/loc block splitting on setitem (manifests with integer-like dtypes, e.g. datetime64) (GH8607)
Bug when doing label based indexing with integers not found in the index for non-unique but monotonic indexes
(GH8680).
Bug when indexing a Float64Index with np.nan on numpy 1.7 (GH8980).
Fix shape attribute for MultiIndex (GH8609)
Bug in GroupBy where a name conflict between the grouper and columns would break groupby operations
(GH7115, GH8112)
Fixed a bug where plotting a column y and specifying a label would mutate the index name of the original
DataFrame (GH8494)
Fix regression in plotting of a DatetimeIndex directly with matplotlib (GH8614).
Bug in date_range where partially-specified dates would incorporate current date (GH6961)
Bug in Setting by indexer to a scalar value with a mixed-dtype Panel4d was failing (GH8702)
Bug where DataReaders would fail if one of the symbols passed was invalid. Now returns data for valid
symbols and np.nan for invalid (GH8494)
Bug in get_quote_yahoo that wouldnt allow non-float return values (GH5229).
69
A lot of improvements to the rolling and expanding moment funtions, see here
Internal refactoring of the Index class to no longer sub-class ndarray, see Internal Refactoring
dropping support for PyTables less than version 3.0.0, and numexpr less than version 2.1 (GH7990)
Split indexing documentation into Indexing and Selecting Data and MultiIndex / Advanced Indexing
Split out string methods documentation into Working with Text Data
Check the API Changes and deprecations before updating
Other Enhancements
Performance Improvements
Bug Fixes
Warning: In 0.15.0 Index has internally been refactored to no longer sub-class ndarray but instead subclass
PandasObject, similarly to the rest of the pandas objects. This change allows very easy sub-classing and
creation of new index types. This should be a transparent change with only very limited API implications (See the
Internal Refactoring)
Warning: The refactorings in Categorical changed the two argument constructor from codes/labels and
levels to values and levels (now called categories). This can lead to subtle bugs. If you use Categorical
directly, please audit your code before updating to this pandas version and change it to use the from_codes()
constructor. See more on Categorical here
70
In [6]: df["grade"]
Out[6]:
0
very good
1
good
2
good
3
very good
4
very good
5
very bad
Name: grade, dtype: category
Categories (5, object): [very bad, bad, medium, good, very good]
In [7]: df.sort("grade")
Out[7]:
id raw_grade
grade
5
6
e
very bad
1
2
b
good
2
3
b
good
0
1
a very good
3
4
a very good
4
5
a very good
In [8]: df.groupby("grade").size()
Out[8]:
grade
very bad
1
bad
0
medium
0
good
2
very good
3
dtype: int64
pandas.core.group_agg and pandas.core.factor_agg were removed. As an alternative, construct a dataframe and use df.groupby(<group>).agg(<func>).
Supplying codes/labels and levels to the Categorical constructor is not supported anymore. Supplying
two arguments to the constructor is now interpreted as values and levels (now called categories). Please
change your code to use the from_codes() constructor.
The Categorical.labels attribute was renamed to Categorical.codes and is read only. If you want
to manipulate codes, please use one of the API methods on Categoricals.
The Categorical.levels attribute is renamed to Categorical.categories.
TimedeltaIndex/Scalar
We introduce a new scalar type Timedelta, which is a subclass of datetime.timedelta, and behaves in a
similar manner, but allows compatibility with np.timedelta64 types as well as a host of custom representation,
parsing, and attributes. This type is very similar to how Timestamp works for datetimes. It is a nice-API box for
the type. See the docs. (GH3009, GH4533, GH8209, GH8187, GH8190, GH7869, GH7661, GH8345, GH8471)
71
Warning: Timedelta scalars (and TimedeltaIndex) component fields are not the same as the component
fields on a datetime.timedelta object. For example, .seconds on a datetime.timedelta object
returns the total number of seconds combined between hours, minutes and seconds. In contrast, the pandas
Timedelta breaks out hours, minutes, microseconds and nanoseconds separately.
# Timedelta accessor
In [9]: tds = Timedelta('31 days 5 min 3 sec')
In [10]: tds.minutes
Out[10]: 5L
In [11]: tds.seconds
Out[11]: 3L
# datetime.timedelta accessor
# this is 5 minutes * 60 + 3 seconds
In [12]: tds.to_pytimedelta().seconds
Out[12]: 303
Note: this is no longer true starting from v0.16.0, where full compatibility with datetime.timedelta is
introduced. See the 0.16.0 whatsnew entry
Warning: Prior to 0.15.0 pd.to_timedelta would return a Series for list-like/Series input, and a
np.timedelta64 for scalar input. It will now return a TimedeltaIndex for list-like input, Series for
Series input, and Timedelta for scalar input.
The arguments to pd.to_timedelta are now (arg,unit=ns,box=True,coerce=False), previously were (arg,box=True,unit=ns) as these are more logical.
Consruct a scalar
In [9]: Timedelta('1 days 06:05:01.00003')
Out[9]: Timedelta('1 days 06:05:01.000030')
In [10]: Timedelta('15.5us')
Out[10]: Timedelta('0 days 00:00:00.000015')
In [11]: Timedelta('1 hour 15.5us')
Out[11]: Timedelta('0 days 01:00:00.000015')
# negative Timedeltas have this string repr
# to be more consistent with datetime.timedelta conventions
In [12]: Timedelta('-1us')
Out[12]: Timedelta('-1 days +23:59:59.999999')
# a NaT
In [13]: Timedelta('nan')
Out[13]: NaT
72
In [17]: td.nanoseconds
Out[17]: 500L
Construct a TimedeltaIndex
In [18]: TimedeltaIndex(['1 days','1 days, 00:00:05',
....:
np.timedelta64(2,'D'),timedelta(days=2,seconds=2)])
....:
Out[18]:
TimedeltaIndex(['1 days 00:00:00', '1 days 00:00:05', '2 days 00:00:00',
'2 days 00:00:02'],
dtype='timedelta64[ns]', freq=None)
73
Finally, the combination of TimedeltaIndex with DatetimeIndex allow certain combination operations that
are NaT preserving:
In [25]: tdi = TimedeltaIndex(['1 days',pd.NaT,'2 days'])
In [26]: tdi.tolist()
Out[26]: [Timedelta('1 days 00:00:00'), NaT, Timedelta('2 days 00:00:00')]
In [27]: dti = date_range('20130101',periods=3)
In [28]: dti.tolist()
Out[28]:
[Timestamp('2013-01-01 00:00:00', offset='D'),
Timestamp('2013-01-02 00:00:00', offset='D'),
Timestamp('2013-01-03 00:00:00', offset='D')]
In [29]: (dti + tdi).tolist()
Out[29]: [Timestamp('2013-01-02 00:00:00'), NaT, Timestamp('2013-01-05 00:00:00')]
In [30]: (dti - tdi).tolist()
Out[30]: [Timestamp('2012-12-31 00:00:00'), NaT, Timestamp('2013-01-01 00:00:00')]
74
complex128
5000 non-null complex128
datetime64[ns]
5000 non-null datetime64[ns]
float64
5000 non-null float64
int64
5000 non-null int64
object
5000 non-null object
timedelta64[ns]
5000 non-null timedelta64[ns]
categorical
5000 non-null category
dtypes: bool(1), category(1), complex128(1), datetime64[ns](1), float64(1), int64(1), object(1), time
memory usage: 303.5+ KB
Additionally memory_usage() is an available method for a dataframe object which returns the memory usage of
each column.
In [37]: df.memory_usage(index=True)
Out[37]:
Index
40000
bool
5000
complex128
80000
datetime64[ns]
40000
float64
40000
int64
40000
object
20000
timedelta64[ns]
40000
categorical
5800
dtype: int64
.dt accessor
Series has gained an accessor to succinctly return datetime like properties for the values of the Series, if its a
datetime/period like Series. (GH7207) This will return a Series, indexed like the existing Series. See the docs
# datetime
In [38]: s = Series(date_range('20130101 09:10:12',periods=4))
In [39]: s
Out[39]:
0
2013-01-01 09:10:12
1
2013-01-02 09:10:12
2
2013-01-03 09:10:12
3
2013-01-04 09:10:12
dtype: datetime64[ns]
In [40]: s.dt.hour
Out[40]:
0
9
1
9
2
9
3
9
dtype: int64
In [41]: s.dt.second
Out[41]:
0
12
1
12
2
12
3
12
dtype: int64
75
In [42]: s.dt.day
Out[42]:
0
1
1
2
2
3
3
4
dtype: int64
In [43]: s.dt.freq
Out[43]: <Day>
76
1
2013
2
2013
3
2013
dtype: int64
In [52]: s.dt.day
Out[52]:
0
1
1
2
2
3
3
4
dtype: int64
# timedelta
In [53]: s = Series(timedelta_range('1 day 00:00:05',periods=4,freq='s'))
In [54]: s
Out[54]:
0
1 days 00:00:05
1
1 days 00:00:06
2
1 days 00:00:07
3
1 days 00:00:08
dtype: timedelta64[ns]
In [55]: s.dt.days
Out[55]:
0
1
1
1
2
1
3
1
dtype: int64
In [56]: s.dt.seconds
Out[56]:
0
5
1
6
2
7
3
8
dtype: int64
In [57]: s.dt.components
Out[57]:
days hours minutes seconds
0
1
0
0
5
1
1
0
0
6
2
1
0
0
7
3
1
0
0
8
milliseconds
0
0
0
0
microseconds
0
0
0
0
nanoseconds
0
0
0
0
77
In [60]: ts.tz_localize(None)
Out[60]: Timestamp('2014-08-01 09:00:00')
In [61]: didx = DatetimeIndex(start='2014-08-01 09:00', freq='H', periods=10, tz='US/Eastern')
In [62]: didx
Out[62]:
DatetimeIndex(['2014-08-01 09:00:00-04:00', '2014-08-01 10:00:00-04:00',
'2014-08-01 11:00:00-04:00', '2014-08-01 12:00:00-04:00',
'2014-08-01 13:00:00-04:00', '2014-08-01 14:00:00-04:00',
'2014-08-01 15:00:00-04:00', '2014-08-01 16:00:00-04:00',
'2014-08-01 17:00:00-04:00', '2014-08-01 18:00:00-04:00'],
dtype='datetime64[ns, US/Eastern]', freq='H')
In [63]: didx.tz_localize(None)
Out[63]:
DatetimeIndex(['2014-08-01 09:00:00',
'2014-08-01 11:00:00',
'2014-08-01 13:00:00',
'2014-08-01 15:00:00',
'2014-08-01 17:00:00',
dtype='datetime64[ns]',
'2014-08-01
'2014-08-01
'2014-08-01
'2014-08-01
'2014-08-01
freq='H')
10:00:00',
12:00:00',
14:00:00',
16:00:00',
18:00:00'],
tz_localize now accepts the ambiguous keyword which allows for passing an array of bools indicating
whether the date belongs in DST or not, NaT for setting transition times to NaT, infer for inferring DST/nonDST, and raise (default) for an AmbiguousTimeError to be raised. See the docs for more details (GH7943)
DataFrame.tz_localize and DataFrame.tz_convert now accepts an optional level argument
for localizing a specific level of a MultiIndex (GH7846)
Timestamp.tz_localize and Timestamp.tz_convert now raise TypeError in error cases, rather
than Exception (GH8025)
a timeseries/index localized to UTC when inserted into a Series/DataFrame will preserve the UTC timezone
(rather than being a naive datetime64[ns]) as object dtype (GH8411)
Timestamp.__repr__ displays dateutil.tz.tzoffset info (GH7907)
Rolling/Expanding Moments improvements
rolling_min(), rolling_max(), rolling_cov(), and rolling_corr() now return objects with
all NaN when len(arg) < min_periods <= window rather than raising. (This makes all rolling functions consistent in this behavior). (GH7766)
Prior to 0.15.0
In [64]: s = Series([10, 11, 12, 13])
In [15]: rolling_min(s, window=10, min_periods=5)
ValueError: min_periods (5) must be <= window (4)
New behavior
In [65]: rolling_min(s, window=10, min_periods=5)
Out[65]:
0
NaN
1
NaN
2
NaN
78
3
NaN
dtype: float64
rolling_window() now normalizes the weights properly in rolling mean mode (mean=True) so that the
calculated weighted means (e.g. triang, gaussian) are distributed about the same means as those calculated
without weighting (i.e. boxcar). See the note on normalization for further details. (GH7618)
In [67]: s = Series([10.5, 8.8, 11.4, 9.7, 9.3])
New behavior
In [68]: rolling_window(s, window=3, win_type='triang', center=True)
Out[68]:
0
NaN
1
9.875
2
10.325
3
10.025
4
NaN
dtype: float64
79
Removed center argument from all expanding_ functions (see list), as the results produced when
center=True did not make much sense. (GH7925)
Added optional ddof argument to expanding_cov() and rolling_cov(). The default value of 1 is
backwards-compatible. (GH8279)
Documented the ddof argument to expanding_var(), expanding_std(), rolling_var(), and
rolling_std(). These functions support of a ddof argument (with a default value of 1) was previously
undocumented. (GH8064)
ewma(), ewmstd(), ewmvol(), ewmvar(), ewmcov(), and ewmcorr() now interpret min_periods
in the same manner that the rolling_*() and expanding_*() functions do: a given result entry will be
NaN if the (expanding, in this case) window does not contain at least min_periods values. The previous
behavior was to set to NaN the min_periods entries starting with the first non- NaN value. (GH7977)
Prior behavior (note values start at index 2, which is min_periods after index 0 (the index of the first nonempty value)):
In [69]: s
New behavior (note values start at index 4, the location of the 2nd (since min_periods=2) non-empty value):
In [70]: ewma(s, com=3., min_periods=2)
Out[70]:
0
NaN
1
NaN
2
NaN
3
NaN
4
1.759644
5
2.383784
dtype: float64
ewmstd(), ewmvol(), ewmvar(), ewmcov(), and ewmcorr() now have an optional adjust argument, just like ewma() does, affecting how the weights are calculated. The default value of adjust is True,
which is backwards-compatible. See Exponentially weighted moment functions for details. (GH7911)
ewma(), ewmstd(), ewmvol(), ewmvar(), ewmcov(), and ewmcorr() now have an optional
ignore_na argument. When ignore_na=False (the default), missing values are taken into account in
the weights calculation. When ignore_na=True (which reproduces the pre-0.15.0 behavior), missing values
are ignored in the weights calculation. (GH7543)
In [71]: ewma(Series([None, 1., 8.]), com=2.)
Out[71]:
0
NaN
1
1.0
2
5.2
dtype: float64
In [72]: ewma(Series([1., None, 8.]), com=2., ignore_na=True)
Out[72]:
80
# pre-0.15.0 behavior
0
1.0
1
1.0
2
5.2
dtype: float64
In [73]: ewma(Series([1., None, 8.]), com=2., ignore_na=False)
Out[73]:
0
1.000000
1
1.000000
2
5.846154
dtype: float64
# new default
Warning: By default (ignore_na=False) the ewm*() functions weights calculation in the presence
of missing values is different than in pre-0.15.0 versions. To reproduce the pre-0.15.0 calculation of weights
in the presence of missing values one must specify explicitly ignore_na=True.
Bug in expanding_cov(), expanding_corr(), rolling_cov(), rolling_cor(), ewmcov(),
and ewmcorr() returning results with columns sorted by name and producing an error for non-unique
columns; now handles non-unique columns and returns columns in original order (except for the case of two
DataFrames with pairwise=False, where behavior is unchanged) (GH7542)
Bug in rolling_count() and expanding_*() functions unnecessarily producing error message for
zero-length data (GH8056)
Bug in rolling_apply()
min_periods=1 (GH8080)
and
expanding_apply()
interpreting
min_periods=0
as
Bug in expanding_std() and expanding_var() for a single value producing a confusing error message
(GH7900)
Bug in rolling_std() and rolling_var() for a single value producing 0 rather than NaN (GH7900)
Bug in ewmstd(), ewmvol(), ewmvar(), and ewmcov() calculation of de-biasing factors when
bias=False (the default). Previously an incorrect constant factor was used, based on adjust=True,
ignore_na=True, and an infinite number of observations. Now a different factor is used for each entry,
based on the actual weights (analogous to the usual N/(N-1) factor). In particular, for a single point a value of
NaN is returned when bias=False, whereas previously a value of (approximately) 0 was returned.
For example, consider the following pre-0.15.0 results for ewmvar(..., bias=False), and the corresponding debiasing factors:
In [74]: s = Series([1., 2., 0., 4.])
In [89]: ewmvar(s, com=2., bias=False)
Out[89]:
0
-2.775558e-16
1
3.000000e-01
2
9.556787e-01
3
3.585799e+00
dtype: float64
In [90]: ewmvar(s, com=2., bias=False) / ewmvar(s, com=2., bias=True)
Out[90]:
0
1.25
1
1.25
2
1.25
3
1.25
dtype: float64
81
Note that entry 0 is approximately 0, and the debiasing factors are a constant 1.25. By comparison, the following
0.15.0 results have a NaN for entry 0, and the debiasing factors are decreasing (towards 1.25):
In [75]: ewmvar(s, com=2., bias=False)
Out[75]:
0
NaN
1
0.500000
2
1.210526
3
4.089069
dtype: float64
In [76]: ewmvar(s, com=2., bias=False) / ewmvar(s, com=2., bias=True)
Out[76]:
0
NaN
1
2.083333
2
1.583333
3
1.425439
dtype: float64
82
API changes related to the introduction of the Timedelta scalar (see above for more details):
Prior to 0.15.0 to_timedelta() would return a Series for list-like/Series input, and a
np.timedelta64 for scalar input. It will now return a TimedeltaIndex for list-like input, Series
for Series input, and Timedelta for scalar input.
For API changes related to the rolling and expanding functions, see detailed overview above.
Other notable API changes:
Consistency when indexing with .loc and a list-like indexer when no values are found.
In [77]: df = DataFrame([['a'],['b']],index=[1,2])
In [78]: df
Out[78]:
0
1 a
2 b
83
Out[82]:
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 3 (major_axis) x 4 (minor_axis)
Items axis: ItemA to ItemB
Major_axis axis: 1 to 3
Minor_axis axis: A to D
Furthermore, .loc will raise If no values are found in a multi-index with a list-like indexer:
In [84]: s = Series(np.arange(3,dtype='int64'),
....:
index=MultiIndex.from_product([['A'],['foo','bar','baz']],
....:
names=['one','two'])
....:
).sortlevel()
....:
In [85]: s
Out[85]:
one two
A
bar
1
baz
2
foo
0
dtype: int64
In [86]: try:
....:
s.loc[['D']]
....: except KeyError as e:
....:
print("KeyError: " + str(e))
....:
KeyError: 'cannot index a multi-index axis with these keys'
Assigning values to None now considers the dtype when choosing an empty value (GH7941).
Previously, assigning to None in numeric containers changed the dtype to object (or errored, depending on the
call). It now uses NaN:
In [87]: s = Series([1, 2, 3])
In [88]: s.loc[0] = None
In [89]: s
Out[89]:
0
NaN
1
2
2
3
dtype: float64
84
To insert a NaN, you must explicitly use np.nan. See the docs.
In prior versions, updating a pandas object inplace would not reflect in other python references to this object.
(GH8511, GH5104)
In [93]: s = Series([1, 2, 3])
In [94]: s2 = s
In [95]: s += 1.5
Made both the C-based and Python engines for read_csv and read_table ignore empty lines in input as well as
1.7. v0.15.0 (October 18, 2014)
85
whitespace-filled lines, as long as sep is not whitespace. This is an API change that can be controlled by the
keyword parameter skip_blank_lines. See the docs (GH4466)
A timeseries/index localized to UTC when inserted into a Series/DataFrame will preserve the UTC timezone
and inserted as object dtype rather than being converted to a naive datetime64[ns] (GH8411).
Bug in passing a DatetimeIndex with a timezone that was not being retained in DataFrame construction
from a dict (GH7822)
In prior versions this would drop the timezone, now it retains the timezone, but gives a column of object
dtype:
In [98]: i = date_range('1/1/2011', periods=3, freq='10s', tz = 'US/Eastern')
In [99]: i
Out[99]:
DatetimeIndex(['2011-01-01 00:00:00-05:00', '2011-01-01 00:00:10-05:00',
'2011-01-01 00:00:20-05:00'],
dtype='datetime64[ns, US/Eastern]', freq='10S')
In [100]: df = DataFrame( {'a' : i } )
In [101]: df
Out[101]:
a
0 2011-01-01 00:00:00-05:00
1 2011-01-01 00:00:10-05:00
2 2011-01-01 00:00:20-05:00
In [102]: df.dtypes
Out[102]:
a
datetime64[ns, US/Eastern]
dtype: object
Previously this would have yielded a column of datetime64 dtype, but without timezone info.
The behaviour of assigning a column to an existing dataframe as df[a] = i remains unchanged (this already
returned an object column with a timezone).
When passing multiple levels to stack(), it will now raise a ValueError when the levels arent all level
names or all level numbers (GH7660). See Reshaping by stacking and unstacking.
Raise a ValueError in df.to_hdf with fixed format, if df has non-unique columns as the resulting file
will be broken (GH7761)
SettingWithCopy raise/warnings (according to the option mode.chained_assignment) will now be
issued when setting a value on a sliced mixed-dtype DataFrame using chained-assignment. (GH7845, GH7950)
In [1]: df = DataFrame(np.arange(0,9), columns=['count'])
In [2]: df['group'] = 'b'
In [3]: df.iloc[0:5]['group'] = 'a'
/usr/local/bin/ipython:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
merge, DataFrame.merge, and ordered_merge now return the same type as the left argument
(GH7737).
86
Previously an enlargement with a mixed-dtype frame would act unlike .append which will preserve dtypes
(related GH2578, GH8176):
In [103]: df = DataFrame([[True, 1],[False, 2]],
.....:
columns=["female","fitness"])
.....:
In [104]: df
Out[104]:
female fitness
0
True
1
1 False
2
In [105]: df.dtypes
Out[105]:
female
bool
fitness
int64
dtype: object
# dtypes are now preserved
In [106]: df.loc[2] = df.loc[1]
In [107]: df
Out[107]:
female fitness
0
True
1
1 False
2
2 False
2
In [108]: df.dtypes
Out[108]:
female
bool
fitness
int64
dtype: object
string
when
path=None,
matching
the
behaviour
of
read_hdf now raises IOError when a file that doesnt exist is passed in. Previously, a new, empty file was
created, and a KeyError raised (GH7715).
DataFrame.info() now ends its output with a newline character (GH8114)
Concatenating no objects will now raise a ValueError rather than a bare Exception.
Merge errors will now be sub-classes of ValueError rather than raw Exception (GH8501)
DataFrame.plot and Series.plot keywords are now have consistent orders (GH8037)
Internal Refactoring
In 0.15.0 Index has internally been refactored to no longer sub-class ndarray but instead subclass
PandasObject, similarly to the rest of the pandas objects. This change allows very easy sub-classing and creation of new index types. This should be a transparent change with only very limited API implications (GH5080,
GH7439, GH7796, GH8024, GH8367, GH7997, GH8522):
you may need to unpickle pandas version < 0.15.0 pickles using pd.read_pickle rather than
pickle.load. See pickle docs
87
when plotting with a PeriodIndex, the matplotlib internal axes will now be arrays of Period rather than a
PeriodIndex (this is similar to how a DatetimeIndex passes arrays of datetimes now)
MultiIndexes will now raise similary to other pandas objects w.r.t. truth testing, see here (GH7897).
When plotting a DatetimeIndex directly with matplotlibs plot function, the axis labels will no longer be formatted as dates but as integers (the internal representation of a datetime64). UPDATE This is fixed in 0.15.1,
see here.
Deprecations
The attributes Categorical labels and levels attributes are deprecated and renamed to codes and
categories.
The outtype argument to pd.DataFrame.to_dict has been deprecated in favor of orient. (GH7840)
The convert_dummies method has been deprecated in favor of get_dummies (GH8140)
The infer_dst argument in tz_localize will be deprecated in favor of ambiguous to allow for more
flexibility in dealing with DST transitions. Replace infer_dst=True with ambiguous=infer for the
same behavior (GH7943). See the docs for more details.
The top-level pd.value_range has been deprecated and can be replaced by .describe() (GH8481)
The Index set operations + and - were deprecated in order to provide these for numeric type operations on
certain index types. + can be replaced by .union() or |, and - by .difference(). Further the method
name Index.diff() is deprecated and can be replaced by Index.difference() (GH8226)
# +
Index(['a','b','c']) + Index(['b','c','d'])
# should be replaced by
Index(['a','b','c']).union(Index(['b','c','d']))
# Index(['a','b','c']) - Index(['b','c','d'])
# should be replaced by
Index(['a','b','c']).difference(Index(['b','c','d']))
The infer_types argument to read_html() now has no effect and is deprecated (GH7762, GH7032).
Removal of prior version deprecations/changes
Remove DataFrame.delevel method in favor of DataFrame.reset_index
1.7.3 Enhancements
Enhancements in the importing/exporting of Stata files:
Added support for bool, uint8, uint16 and uint32 datatypes in to_stata (GH7097, GH7365)
Added conversion option when importing Stata files (GH8527)
DataFrame.to_stata and StataWriter check string length for compatibility with limitations imposed
in dta files where fixed-width strings must contain 244 or fewer characters. Attempting to write Stata dta files
with strings longer than 244 characters raises a ValueError. (GH7858)
88
read_stata and StataReader can import missing data information into a DataFrame by setting
the argument convert_missing to True. When using this options, missing values are returned as
StataMissingValue objects and columns containing missing values have object data type. (GH8045)
Enhancements in the plotting functions:
Added layout keyword to DataFrame.plot. You can pass a tuple of (rows, columns), one of which
can be -1 to automatically infer (GH6667, GH8071).
Allow to pass multiple axes to DataFrame.plot, hist and boxplot (GH5353, GH6970, GH7069)
Added support for c, colormap
kind=scatter (GH7780)
and
colorbar
arguments
for
DataFrame.plot
with
89
count
unique
top
freq
mean
std
min
25%
50%
75%
max
24
2
foo
16
NaN
NaN
NaN
NaN
NaN
NaN
NaN
24
4
d
6
NaN
NaN
NaN
NaN
NaN
NaN
NaN
24.000000
NaN
NaN
NaN
11.500000
7.071068
0.000000
5.750000
11.500000
17.250000
23.000000
24.000000
NaN
NaN
NaN
12.000000
7.071068
0.500000
6.250000
12.000000
17.750000
23.500000
Without those arguments, describe will behave as before, including only numerical columns or, if none are,
only categorical columns. See also the docs
Added split as an option to the orient argument in pd.DataFrame.to_dict. (GH7840)
The get_dummies method can now be used on DataFrames. By default only catagorical columns are encoded
as 0s and 1s, while other columns are left untouched.
In [113]: df = DataFrame({'A': ['a', 'b', 'a'], 'B': ['c', 'c', 'b'],
.....:
'C': [1, 2, 3]})
.....:
In [114]: pd.get_dummies(df)
Out[114]:
C A_a A_b B_b B_c
0 1
1
0
0
1
1 2
0
1
0
1
2 3
1
0
1
0
90
If Period freq is D, H, T, S, L, U, N, Timedelta-like can be added if the result can have same freq. Otherwise,
only the same offsets can be added.
In [118]: idx = pd.period_range('2014-07-01 09:00', periods=5, freq='H')
In [119]: idx
Out[119]:
PeriodIndex(['2014-07-01 09:00', '2014-07-01 10:00', '2014-07-01 11:00',
'2014-07-01 12:00', '2014-07-01 13:00'],
dtype='int64', freq='H')
In [120]: idx + pd.offsets.Hour(2)
Out[120]:
PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
'2014-07-01 14:00', '2014-07-01 15:00'],
dtype='int64', freq='H')
In [121]: idx + Timedelta('120m')
Out[121]:
PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
'2014-07-01 14:00', '2014-07-01 15:00'],
dtype='int64', freq='H')
In [122]: idx = pd.period_range('2014-07', periods=5, freq='M')
In [123]: idx
Out[123]: PeriodIndex(['2014-07', '2014-08', '2014-09', '2014-10', '2014-11'], dtype='int64', fr
Added experimental compatibility with openpyxl for versions >= 2.0. The DataFrame.to_excel method
engine keyword now recognizes openpyxl1 and openpyxl2 which will explicitly require openpyxl v1
and v2 respectively, failing if the requested version is not available. The openpyxl engine is a now a metaengine that automatically uses whichever version of openpyxl is installed. (GH7177)
DataFrame.fillna can now accept a DataFrame as a fill value (GH8377)
Passing multiple levels to stack() will now work when multiple level numbers are passed (GH7660). See
Reshaping by stacking and unstacking.
set_names(), set_labels(), and set_levels() methods now take an optional level keyword argument to all modification of specific level(s) of a MultiIndex. Additionally set_names() now accepts a
scalar string value when operating on an Index or on a specific level of a MultiIndex (GH7792)
91
Out[128]:
MultiIndex(levels=[[u'a'], [u'a', u'b', u'c'], [u'p', u'q', u'r']],
labels=[[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 1, 2, 0, 1, 2,
names=[u'foo', u'bar', u'baz'])
In [129]: idx.set_levels([['a','b','c'],[1,2,3]], level=[1,2])
Out[129]:
MultiIndex(levels=[[u'a'], [u'a', u'b', u'c'], [1, 2, 3]],
labels=[[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 1, 2, 0, 1, 2,
names=[u'foo', u'bar', u'baz'])
Index.isin now supports a level argument to specify which index level to use for membership tests
(GH7892, GH7890)
In [1]: idx = MultiIndex.from_product([[0, 1], ['a', 'b', 'c']])
In [2]: idx.values
Out[2]: array([(0, 'a'), (0, 'b'), (0, 'c'), (1, 'a'), (1, 'b'), (1, 'c')], dtype=object)
In [3]: idx.isin(['a', 'c', 'e'], level=1)
Out[3]: array([ True, False, True, True, False,
True], dtype=bool)
True,
True], dtype=bool)
In [133]: idx.drop_duplicates()
Out[133]: Int64Index([1, 2, 3, 4], dtype='int64')
add copy=True argument to pd.concat to enable pass thru of complete blocks (GH8252)
Added support for numpy 1.8+ data types (bool_, int_, float_, string_) for conversion to R dataframe
(GH8400)
1.7.4 Performance
Performance improvements in DatetimeIndex.__iter__ to allow faster iteration (GH7683)
Performance improvements in Period creation (and PeriodIndex setitem) (GH5155)
Improvements in Series.transform for significant performance gains (revised) (GH6496)
Performance improvements in StataReader when reading large files (GH8040, GH8073)
Performance improvements in StataWriter when writing large files (GH8079)
Performance and memory usage improvements in multi-key groupby (GH8128)
Performance improvements in groupby .agg and .apply where builtins max/min were not mapped to
numpy/cythonized versions (GH7722)
Performance improvement in writing to sql (to_sql) of up to 50% (GH8208).
Performance benchmarking of groupby for large value of ngroups (GH6787)
92
93
Bug in get where an IndexError would not cause the default value to be returned (GH7725)
Bug in offsets.apply, rollforward and rollback may reset nanosecond (GH7697)
Bug in offsets.apply, rollforward and rollback may raise AttributeError if Timestamp
has dateutil tzinfo (GH7697)
Bug in sorting a multi-index frame with a Float64Index (GH8017)
Bug in inconsistent panel setitem with a rhs of a DataFrame for alignment (GH7763)
Bug in is_superperiod and is_subperiod cannot handle higher frequencies than S (GH7760, GH7772,
GH7803)
Bug in 32-bit platforms with Series.shift (GH8129)
Bug in PeriodIndex.unique returns int64 np.ndarray (GH7540)
Bug in groupby.apply with a non-affecting mutation in the function (GH8467)
Bug in DataFrame.reset_index which has MultiIndex
DatetimeIndex with tz raises ValueError (GH7746, GH7793)
contains
PeriodIndex
or
Bug in DataFrame.plot with subplots=True may draw unnecessary minor xticks and yticks (GH7801)
Bug in StataReader which did not read variable labels in 117 files due to difference between Stata documentation and implementation (GH7816)
Bug in StataReader where strings were always converted to 244 characters-fixed width irrespective of underlying string size (GH7858)
Bug in DataFrame.plot and Series.plot may ignore rot and fontsize keywords (GH7844)
Bug in DatetimeIndex.value_counts doesnt preserve tz (GH7735)
Bug in PeriodIndex.value_counts results in Int64Index (GH7735)
Bug in DataFrame.join when doing left join on index and there are multiple matches (GH5391)
Bug in GroupBy.transform() where int groups with a transform that didnt preserve the index were incorrectly truncated (GH7972).
Bug in groupby where callable objects without name attributes would take the wrong path, and produce a
DataFrame instead of a Series (GH7929)
Bug in groupby error message when a DataFrame grouping column is duplicated (GH7511)
Bug in read_html where the infer_types argument forced coercion of date-likes incorrectly (GH7762,
GH7032).
Bug in Series.str.cat with an index which was filtered as to not include the first item (GH7857)
Bug in Timestamp cannot parse nanosecond from string (GH7878)
Bug in Timestamp with string offset and tz results incorrect (GH7833)
Bug in tslib.tz_convert and tslib.tz_convert_single may return different results (GH7798)
Bug in DatetimeIndex.intersection of non-overlapping timestamps with tz raises IndexError
(GH7880)
Bug in alignment with TimeOps and non-unique indexes (GH8363)
Bug in GroupBy.filter() where fast path vs. slow path made the filter return a non scalar value that
appeared valid but wasnt (GH7870).
Bug in date_range()/DatetimeIndex() when the timezone was inferred from input dates yet incorrect
times were returned when crossing DST boundaries (GH7835, GH7901).
94
Bug in to_excel() where a negative sign was being prepended to positive infinity and was absent for negative
infinity (GH7949)
Bug in area plot draws legend with incorrect alpha when stacked=True (GH8027)
Period and PeriodIndex addition/subtraction with np.timedelta64 results in incorrect internal representations (GH7740)
Bug in Holiday with no offset or observance (GH7987)
Bug in DataFrame.to_latex formatting when columns or index is a MultiIndex (GH7982).
Bug in DateOffset around Daylight Savings Time produces unexpected results (GH5175).
Bug in DataFrame.shift where empty columns would throw ZeroDivisionError on numpy 1.7
(GH8019)
Bug in installation where html_encoding/*.html wasnt installed and therefore some tests were not running correctly (GH7927).
Bug in read_html where bytes objects were not tested for in _read (GH7927).
Bug in DataFrame.stack() when one of the column levels was a datelike (GH8039)
Bug in broadcasting numpy scalars with DataFrame (GH8116)
Bug in pivot_table performed with nameless index and columns raises KeyError (GH8103)
Bug in DataFrame.plot(kind=scatter) draws points and errorbars with different colors when the
color is specified by c keyword (GH8081)
Bug in Float64Index where iat and at were not testing and were failing (GH8092).
Bug in DataFrame.boxplot() where y-limits were not set correctly when producing multiple axes
(GH7528, GH5517).
Bug in read_csv where line comments were not handled correctly given a custom line terminator or
delim_whitespace=True (GH8122).
Bug in read_html where empty tables caused a StopIteration (GH7575)
Bug in casting when setting a column in a same-dtype block (GH7704)
Bug in accessing groups from a GroupBy when the original grouper was a tuple (GH8121).
Bug in .at that would accept integer indexers on a non-integer index and do fallback (GH7814)
Bug with kde plot and NaNs (GH8182)
Bug in GroupBy.count with float32 data type were nan values were not excluded (GH8169).
Bug with stacked barplots and NaNs (GH8175).
Bug in resample with non evenly divisible offsets (e.g. 7s) (GH8371)
Bug in interpolation methods with the limit keyword when no values needed interpolating (GH7173).
Bug where col_space was ignored in DataFrame.to_string() when header=False (GH8230).
Bug with DatetimeIndex.asof incorrectly matching partial strings and returning the wrong date
(GH8245).
Bug in plotting methods modifying the global matplotlib rcParams (GH8242).
Bug in DataFrame.__setitem__ that caused errors when setting a dataframe column to a sparse array
(GH8131)
Bug where Dataframe.boxplot() failed when entire column was empty (GH8181).
95
Experimental Changes
Bug Fixes
# new behaviour
In [1]: d + offsets.MonthEnd()
Out[1]: Timestamp('2014-01-31 09:00:00')
In [2]: d + offsets.MonthEnd(normalize=True)
Out[2]: Timestamp('2014-01-31 00:00:00')
Note that for the other offsets the default behaviour did not change.
Add back #N/A N/A as a default NA value in text parsing, (regresion from 0.12) (GH5521)
Raise a TypeError on inplace-setting with a .where and a non np.nan value as this is inconsistent with a
set-item expression like df[mask] = None (GH7656)
1.8.2 Enhancements
Add dropna argument to value_counts and nunique (GH5569).
Add select_dtypes() method to allow selection of columns based on dtype (GH7316). See the docs.
All offsets suppports the normalize keyword to specify whether offsets.apply, rollforward
and rollback resets the time (hour, minute, etc) or not (default False, preserves time) (GH7156):
In [3]: import pandas.tseries.offsets as offsets
In [4]: day = offsets.Day()
97
1.8.3 Performance
Improvements in dtype inference for numeric operations involving yielding performance gains for dtypes:
int64, timedelta64, datetime64 (GH7223)
Improvements in Series.transform for significant performance gains (GH6496)
98
Improvements in DataFrame.transform with ufuncs and built-in grouper functions for signifcant performance
gains (GH7383)
Regression in groupby aggregation of datetime64 dtypes (GH7555)
Improvements in MultiIndex.from_product for large iterables (GH7627)
1.8.4 Experimental
pandas.io.data.Options has a new method, get_all_data method, and now consistently returns a
multi-indexed DataFrame, see the docs. (GH5602)
io.gbq.read_gbq and io.gbq.to_gbq were refactored to remove the dependency on the Google
bq.py command line client. This submodule now uses httplib2 and the Google apiclient and
oauth2client API client libraries which should be more stable and, therefore, reliable than bq.py. See the
docs. (GH6937).
99
100
Bug in StataReader when reading Stata 13 (117) files containing fixed width strings (GH7360)
Bug in StataWriter where encoding was ignored (GH7286)
Bug in DatetimeIndex comparison doesnt handle NaT properly (GH7529)
Bug in passing input with tzinfo to some offsets apply, rollforward or rollback resets tzinfo or
raises ValueError (GH7465)
Bug in DatetimeIndex.to_period, PeriodIndex.asobject, PeriodIndex.to_timestamp
doesnt preserve name (GH7485)
Bug in DatetimeIndex.to_period and PeriodIndex.to_timestanp handle NaT incorrectly
(GH7228)
Bug in offsets.apply, rollforward and rollback may return normal datetime (GH7502)
Bug in resample raises ValueError when target contains NaT (GH7227)
Bug in Timestamp.tz_localize resets nanosecond info (GH7534)
Bug in DatetimeIndex.asobject raises ValueError when it contains NaT (GH7539)
Bug in Timestamp.__new__ doesnt preserve nanosecond properly (GH7610)
Bug in Index.astype(float) where it would return an object dtype Index (GH7464).
Bug in DataFrame.reset_index loses tz (GH3950)
Bug in DatetimeIndex.freqstr raises AttributeError when freq is None (GH7606)
Bug in GroupBy.size created by TimeGrouper raises AttributeError (GH7453)
Bug in single column bar plot is misaligned (GH7498).
Bug in area plot with tz-aware time series raises ValueError (GH7471)
Bug in non-monotonic Index.union may preserve name incorrectly (GH7458)
Bug in DatetimeIndex.intersection doesnt preserve timezone (GH4690)
Bug in rolling_var where a window larger than the array would raise an error(GH7297)
Bug with last plotted timeseries dictating xlim (GH2960)
Bug with secondary_y axis not being considered for timeseries xlim (GH3490)
Bug in Float64Index assignment with a non scalar indexer (GH7586)
Bug in pandas.core.strings.str_contains does not properly match in a case insensitive fashion
when regex=False and case=False (GH7505)
Bug in expanding_cov, expanding_corr, rolling_cov, and rolling_corr for two arguments
with mismatched index (GH7512)
Bug in to_sql taking the boolean column as text column (GH7678)
Bug in grouped hist doesnt handle rot kw and sharex kw properly (GH7234)
Bug in .loc performing fallback integer indexing with object dtype indices (GH7496)
Bug (regression) in PeriodIndex constructor when passed Series objects (GH7701).
101
102
A
B
0 1.583584 -0.438313
1 -0.402537 -0.780572
2 -0.141685 0.542241
3 0.370966 -0.251642
4 0.787484 1.666563
In [3]: dfl.iloc[:,2:3]
Out[3]:
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3, 4]
In [4]: dfl.iloc[:,1:3]
Out[4]:
B
0 -0.438313
1 -0.780572
2 0.542241
3 -0.251642
4 1.666563
In [5]: dfl.iloc[4:6]
Out[5]:
A
B
4 0.787484 1.666563
Slicing with negative start, stop & step values handles corner cases better (GH6531):
df.iloc[:-len(df)] is now empty
df.iloc[len(df)::-1] now enumerates all elements in reverse
The DataFrame.interpolate() keyword downcast default has been changed from infer to None.
This is to preseve the original dtype unless explicitly requested otherwise (GH6290).
When converting a dataframe to HTML it used to return Empty DataFrame. This special case has been removed,
instead a header with the column names is returned (GH6062).
Series
and
Index
now
internall
share
more
common
operations,
e.g.
factorize(),nunique(),value_counts() are now supported on Index types as well.
The Series.weekday property from is removed from Series for API consistency.
Using a
DatetimeIndex/PeriodIndex method on a Series will now raise a TypeError. (GH4551, GH4056,
GH5519, GH6380, GH7206).
Add
is_month_start,
is_month_end,
is_quarter_start,
is_quarter_end,
is_year_start, is_year_end accessors for DateTimeIndex / Timestamp which return a
boolean array of whether the timestamp(s) are at the start/end of the month/quarter/year defined by the
frequency of the DateTimeIndex / Timestamp (GH4565, GH6998)
Local variable usage has changed in pandas.eval()/DataFrame.eval()/DataFrame.query()
(GH5987). For the DataFrame methods, two things have changed
103
In [9]: i[[0,1,2]].astype(np.int_)
Out[9]: Int64Index([1, 2, 3], dtype='int32')
set_index no longer converts MultiIndexes to an Index of tuples. For example, the old behavior returned an
Index in this case (GH6459):
# Old behavior, casted MultiIndex to an Index
In [10]: tuple_ind
Out[10]: Index([(u'a', u'c'), (u'a', u'd'), (u'b', u'c'), (u'b', u'd')], dtype='object')
In [11]: df_multi.set_index(tuple_ind)
Out[11]:
0
1
(a, c) 0.471435 -1.190976
(a, d) 1.432707 -0.312652
(b, c) -0.720589 0.887163
(b, d) 0.859588 -0.636524
# New behavior
In [12]: mi
Out[12]:
MultiIndex(levels=[[u'a', u'b'], [u'c', u'd']],
labels=[[0, 0, 1, 1], [0, 1, 0, 1]])
In [13]: df_multi.set_index(mi)
Out[13]:
0
1
a c 0.471435 -1.190976
d 1.432707 -0.312652
104
b c -0.720589 0.887163
d 0.859588 -0.636524
pairwise keyword was added to the statistical moment functions rolling_cov, rolling_corr,
ewmcov, ewmcorr, expanding_cov, expanding_corr to allow the calculation of moving window
covariance and correlation matrices (GH4950). See Computing rolling pairwise covariances and correlations
in the docs.
In [16]: df = DataFrame(np.random.randn(10,4),columns=list('ABCD'))
In [17]: covs = rolling_cov(df[['A','B','C']], df[['B','C','D']], 5, pairwise=True)
In [18]: covs[df.index[-1]]
Out[18]:
B
C
D
A 0.128104 0.183628 -0.047358
B 0.856265 0.058945 0.145447
C 0.058945 0.335350 0.390637
Series.iteritems() is now lazy (returns an iterator rather than a list). This was the documented behavior
prior to 0.14. (GH6760)
Added nunique and value_counts functions to Index for counting unique elements. (GH6734)
stack and unstack now raise a ValueError when the level keyword refers to a non-unique item in the
Index (previously raised a KeyError). (GH6738)
drop unused order argument from Series.sort; args now are in the same order as Series.order; add
na_position arg to conform to Series.order (GH6847)
default sorting algorithm for Series.order is now quicksort, to conform with Series.sort (and
numpy defaults)
add inplace keyword to Series.order/sort to make them inverses (GH6859)
DataFrame.sort now places NaNs at the beginning or end of the sort according to the na_position
parameter. (GH3917)
accept TextFileReader in concat, which was affecting a common user idiom (GH6583), this was a
regression from 0.13.1
105
Added factorize functions to Index and Series to get indexer and unique values (GH7090)
describe on a DataFrame with a mix of Timestamp and string like objects returns a different Index (GH7088).
Previously the index was unintentionally sorted.
Arithmetic operations with only bool dtypes now give a warning indicating that they are evaluated in Python
space for +, -, and * operations and raise for all others (GH7011, GH6762, GH7015, GH7210)
x
y
x
x
=
=
+
/
In HDFStore, select_as_multiple will always raise a KeyError, when a key or the selector is not
found (GH6177)
df[col] = value and df.loc[:,col] = value are now completely equivalent; previously the
.loc would not necessarily coerce the dtype of the resultant series (GH6149)
dtypes and ftypes now return a series with dtype=object on empty containers (GH5740)
df.to_csv will now return a string of the CSV data if neither a target path nor a buffer is provided (GH6061)
pd.infer_freq() will now raise a TypeError if given an invalid Series/Index type (GH6407,
GH6463)
A tuple passed to DataFame.sort_index will be interpreted as the levels of the index, rather than requiring
a list of tuple (GH4370)
all offset operations now return Timestamp types (rather than datetime), Business/Week frequencies were
incorrect (GH4069)
to_excel now converts np.inf into a string representation, customizable by the inf_rep keyword argument (Excel has no native inf representation) (GH6782)
Replace pandas.compat.scipy.scoreatpercentile with numpy.percentile (GH6810)
.quantile on a datetime[ns] series now returns Timestamp instead of np.datetime64 objects
(GH6810)
change AssertionError to TypeError for invalid types passed to concat (GH6583)
Raise a TypeError when DataFrame is passed an iterator as the data argument (GH5357)
106
In the current version, large DataFrames are centrally truncated, showing a preview of head and tail in both
dimensions.
allow option truncate for display.show_dimensions to only show the dimensions if the frame is
truncated (GH6547).
The default for display.show_dimensions will now be truncate. This is consistent with how Series
display length.
107
..
4
.. ...
20 ...
..
24
[5 rows x 5 columns]
# will not show dimensions since it is not truncated
In [21]: with pd.option_context('display.max_rows', 10, 'display.max_columns', 40,
....:
'display.show_dimensions', 'truncate'):
....:
print(dfd)
....:
0
1
2
3
4
0
0
1
2
3
4
1
5
6
7
8
9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
Regression in the display of a MultiIndexed Series with display.max_rows is less than the length of the
series (GH7101)
Fixed a bug in the HTML repr of a truncated Series or DataFrame not showing the class name with the large_repr
set to info (GH7105)
The verbose keyword in DataFrame.info(), which controls whether to shorten the info representation,
is now None by default. This will follow the global setting in display.max_info_columns. The global
setting can be overriden with verbose=True or verbose=False.
Fixed a bug with the info repr not honoring the display.max_info_columns setting (GH6939)
Offset/freq info now in Timestamp __repr__ (GH4553)
specified
Raise
ValueError
when
engine=c
read_csv()/read_table() (GH6607)
with
specified
delim_whitespace=True
with
unsupported
options
in
in
Raise ValueError when fallback to python parser causes options to be ignored (GH6607)
Produce ParserWarning on fallback to python parser when no options are ignored (GH6607)
Translate sep=\s+ to delim_whitespace=True in read_csv()/read_table() if no other Cunsupported options specified (GH6607)
108
In [24]: g.head(1)
Out[24]:
A B
0 1 2
2 5 6
# filters DataFrame
groupby nth now reduces by default; filtering can be achieved by passing as_index=False. With an
optional dropna argument to ignore NaN. See the docs.
Reducing
In [27]: df = DataFrame([[1, np.nan], [1, 4], [5, 6]], columns=['A', 'B'])
In [28]: g = df.groupby('A')
In [29]: g.nth(0)
Out[29]:
B
A
1 NaN
5
6
# this is equivalent to g.first()
In [30]: g.nth(0, dropna='any')
Out[30]:
B
A
1 4
5 6
# this is equivalent to g.last()
In [31]: g.nth(-1, dropna='any')
Out[31]:
B
A
1 4
5 6
Filtering
In [32]: gf = df.groupby('A',as_index=False)
In [33]: gf.nth(0)
Out[33]:
A
B
109
0
2
1 NaN
5
6
groupby will now not return the grouped column for non-cython functions (GH5610, GH5614, GH6732), as its
already the index
In [35]: df = DataFrame([[1, np.nan], [1, 4], [5, 6], [5, 8]], columns=['A', 'B'])
In [36]: g = df.groupby('A')
In [37]: g.count()
Out[37]:
B
A
1 1
5 2
In [38]: g.describe()
Out[38]:
B
A
1 count 1.000000
mean
4.000000
std
NaN
min
4.000000
25%
4.000000
50%
4.000000
75%
4.000000
...
...
5 mean
7.000000
std
1.414214
min
6.000000
25%
6.500000
50%
7.000000
75%
7.500000
max
8.000000
[16 rows x 1 columns]
passing as_index will leave the grouped column in-place (this is not change in 0.14.0)
In [39]: df = DataFrame([[1, np.nan], [1, 4], [5, 6], [5, 8]], columns=['A', 'B'])
In [40]: g = df.groupby('A',as_index=False)
In [41]: g.count()
Out[41]:
A B
0 1 1
1 5 2
In [42]: g.describe()
110
Out[42]:
A
0 count 2
mean
1
std
0
min
1
25%
1
50%
1
75%
1
...
..
1 mean
5
std
0
min
5
25%
5
50%
5
75%
5
max
5
B
1.000000
4.000000
NaN
4.000000
4.000000
4.000000
4.000000
...
7.000000
1.414214
6.000000
6.500000
7.000000
7.500000
8.000000
Allow specification of a more complex groupby via pd.Grouper, such as grouping by a Time and a string
field simultaneously. See the docs. (GH3794)
Better propagation/preservation of Series names when performing groupby operations:
SeriesGroupBy.agg will ensure that the name attribute of the original series is propagated to the
result (GH6265).
If the function provided to GroupBy.apply returns a named series, the name of the series will be kept as
the name of the column index of the DataFrame returned by GroupBy.apply (GH6124). This facilitates
DataFrame.stack operations where the name of the column index is used as the name of the inserted
column containing the pivoted data.
1.9.5 SQL
The SQL reading and writing functions now support more database flavors through SQLAlchemy (GH2717, GH4163,
GH5950, GH6292). All databases supported by SQLAlchemy can be used, such as PostgreSQL, MySQL, Oracle,
Microsoft SQL server (see documentation of SQLAlchemy on included dialects).
The functionality of providing DBAPI connection objects will only be supported for sqlite3 in the future. The
mysql flavor is deprecated.
The new functions read_sql_query() and read_sql_table() are introduced. The function read_sql()
is kept as a convenience wrapper around the other two and will delegate to specific function depending on the provided
input (database table name or sql query).
In practice, you have to provide a SQLAlchemy engine to the sql functions. To connect with SQLAlchemy you use
the create_engine() function to create an engine object from database URI. You only need to create the engine
once per database you are connecting to. For an in-memory sqlite database:
In [43]: from sqlalchemy import create_engine
# Create your connection.
In [44]: engine = create_engine('sqlite:///:memory:')
This engine can then be used to write or read data to/from this database:
111
You can read data from a database by specifying the table name:
In [47]: pd.read_sql_table('db_table', engine)
Out[47]:
A B
0 1 a
1 2 b
2 3 c
112
Warning: You should specify all axes in the .loc specifier, meaning the indexer for the index and for the
columns. Their are some ambiguous cases where the passed indexer could be mis-interpreted as indexing both
axes, rather than into say the MuliIndex for the rows.
You should do this:
df.loc[(slice('A1','A3'),.....),:]
Warning: You will need to make sure that the selection axes are fully lexsorted!
In [49]: def mklbl(prefix,n):
....:
return ["%s%s" % (prefix,i)
....:
for i in range(n)]
a
bar
1
5
9
13
17
21
25
...
229
233
237
241
245
249
253
foo
0
4
8
12
16
20
24
...
228
232
236
240
244
248
252
b
bah
3
7
11
15
19
23
27
...
231
235
239
243
247
251
255
foo
2
6
10
14
18
22
26
...
230
234
238
242
246
250
254
113
It is possible to perform quite complicated selections using this method on multiple axes at the same time.
In [57]: df.loc['A1',(slice(None),'foo')]
Out[57]:
lvl0
a
b
lvl1
foo foo
B0 C0 D0
64
66
D1
68
70
C1 D0
72
74
D1
76
78
C2 D0
80
82
114
D1
C3 D0
...
B1 C0 D1
C1 D0
D1
C2 D0
D1
C3 D0
D1
84
88
...
100
104
108
112
116
120
124
86
90
...
102
106
110
114
118
122
126
Using a boolean indexer you can provide selection related to the values.
In [59]: mask = df[('a','foo')]>200
In [60]: df.loc[idx[mask,:,['C1','C3']],idx[:,'foo']]
Out[60]:
lvl0
a
b
lvl1
foo foo
A3 B0 C1 D1 204 206
C3 D0 216 218
D1 220 222
B1 C1 D0 232 234
D1 236 238
C3 D0 248 250
D1 252 254
You can also specify the axis argument to .loc to interpret the passed slicers on a single axis.
In [61]: df.loc(axis=0)[:,:,['C1','C3']]
Out[61]:
lvl0
a
b
lvl1
bar foo bah foo
A0 B0 C1 D0
9
8
11
10
D1
13
12
15
14
115
C3 D0
D1
B1 C1 D0
D1
C3 D0
...
A3 B0 C1 D1
C3 D0
D1
B1 C1 D0
D1
C3 D0
D1
25
29
41
45
57
...
205
217
221
233
237
249
253
24
28
40
44
56
...
204
216
220
232
236
248
252
27
31
43
47
59
...
207
219
223
235
239
251
255
26
30
42
46
58
...
206
218
222
234
238
250
254
foo
0
4
-10
-10
16
20
-10
...
228
-10
-10
240
244
-10
-10
b
bah
3
7
-10
-10
19
23
-10
...
231
-10
-10
243
247
-10
-10
foo
2
6
-10
-10
18
22
-10
...
230
-10
-10
242
246
-10
-10
116
a
bar
1
5
9000
9000
17
foo
0
4
8000
8000
16
b
bah
3
7
11000
11000
19
foo
2
6
10000
10000
18
D1
C3 D0
...
A3 B1 C0 D1
C1 D0
D1
C2 D0
D1
C3 D0
D1
21
13000
...
229
121000
121000
241
245
125000
125000
20
12000
...
228
120000
120000
240
244
124000
124000
23
15000
...
231
123000
123000
243
247
127000
127000
22
14000
...
230
122000
122000
242
246
126000
126000
1.9.7 Plotting
Hexagonal bin plots from DataFrame.plot with kind=hexbin (GH5478), See the docs.
DataFrame.plot and Series.plot now supports area plot with specifying kind=area (GH6656),
See the docs
Pie plots from Series.plot and DataFrame.plot with kind=pie (GH6976), See the docs.
Plotting with Error Bars is now supported in the .plot method of DataFrame and Series objects (GH3796,
GH6834), See the docs.
DataFrame.plot and Series.plot now support a table keyword for plotting matplotlib.Table,
See the docs. The table keyword can receive the following values.
False: Do nothing (default).
True: Draw a table using the DataFrame or Series called plot method. Data will be transposed to
meet matplotlibs default layout.
DataFrame or Series: Draw matplotlib.table using the passed data.
The data will be
drawn as displayed in print method (not transposed automatically).
Also, helper function
pandas.tools.plotting.table is added to create a table from DataFrame and Series, and
add it to an matplotlib.Axes.
plot(legend=reverse) will now reverse the order of legend labels for most plot kinds. (GH6014)
Line plot and area plot can be stacked by stacked=True (GH6656)
Following keywords are now acceptable for DataFrame.plot() with kind=bar and kind=barh:
width: Specify the bar width. In previous versions, static value 0.5 was passed to matplotlib and it cannot
be overwritten. (GH6604)
align: Specify the bar alignment. Default is center (different from matplotlib). In previous versions,
pandas passes align=edge to matplotlib and adjust the location to center by itself, and it results align
keyword is not applied as expected. (GH4525)
position: Specify relative alignments for bar plot layout. From 0 (left/bottom-end) to 1(right/top-end).
Default is 0.5 (center). (GH6604)
Because of the default align value changes, coordinates of bar plots are now located on integer values (0.0, 1.0,
2.0 ...). This is intended to make bar plot be located on the same coodinates as line plot. However, bar plot
may differs unexpectedly when you manually adjust the bar location or drawing area, such as using set_xlim,
set_ylim, etc. In this cases, please modify your script to meet with new coordinates.
117
1.9.9 Deprecations
The pivot_table()/DataFrame.pivot_table() and crosstab() functions now take arguments
index and columns instead of rows and cols. A FutureWarning is raised to alert that the old rows
and cols arguments will not be supported in a future release (GH5505)
The DataFrame.drop_duplicates() and DataFrame.duplicated() methods now take argument
subset instead of cols to better align with DataFrame.dropna(). A FutureWarning is raised to
alert that the old cols arguments will not be supported in a future release (GH6680)
The DataFrame.to_csv() and DataFrame.to_excel() functions now takes argument columns instead of cols. A FutureWarning is raised to alert that the old cols arguments will not be supported in a
future release (GH6645)
Indexers will warn FutureWarning when used with a scalar indexer and a non-floating point Index (GH4892,
GH6960)
118
In [2]: Series(1,np.arange(5)).iloc[3.0]
pandas/core/index.py:469: FutureWarning: scalar indexers for index type Int64Index shoul
Out[2]: 1
In [3]: Series(1,np.arange(5)).iloc[3.0:4]
pandas/core/index.py:527: FutureWarning: slice indexers when using iloc should be intege
Out[3]:
3
1
dtype: int64
# these are Float64Indexes, so integer or floating point is acceptable
In [4]: Series(1,np.arange(5.))[3]
Out[4]: 1
In [5]: Series(1,np.arange(5.))[3.0]
Out[6]: 1
1.9.11 Enhancements
DataFrame and Series will create a MultiIndex object if passed a tuples dict, See the docs (GH3323)
119
'b'):
'a'):
'c'):
'a'):
'b'):
{('A',
{('A',
{('A',
{('A',
{('A',
'B'):
'C'):
'B'):
'C'):
'D'):
1,
3,
5,
7,
9,
('A',
('A',
('A',
('A',
('A',
'C'):
'B'):
'C'):
'B'):
'B'):
2},
4},
6},
8},
10}})
wealth
196087.3
316478.7
294750.0
120
....:
....:
).set_index(['household_id','asset_id'])
In [73]: portfolio
Out[73]:
household_id asset_id
1
nl0000301109
2
nl0000289783
gb00b03mlx29
3
gb00b03mlx29
lu0197800237
nl0000289965
4
NaN
name
share
ABN Amro
Robeco
Royal Dutch Shell
Royal Dutch Shell
AAB Eastern Europe Equity Fund
Postbank BioTech Fonds
NaN
1.00
0.40
0.60
0.15
0.60
0.25
1.00
share
household_id asset_id
1
nl0000301109
2
nl0000289783
gb00b03mlx29
3
gb00b03mlx29
lu0197800237
nl0000289965
1.00
0.40
0.60
0.15
0.60
0.25
quotechar, doublequote, and escapechar can now be specified when using DataFrame.to_csv
(GH5414, GH4528)
Partially sort by only the specified levels of a MultiIndex with the sort_remaining boolean kwarg.
(GH3984)
Added to_julian_date to TimeStamp and DatetimeIndex. The Julian Date is used primarily in
astronomy and represents the number of days from noon, January 1, 4713 BC. Because nanoseconds are used
to define the time in pandas the actual range of dates that you can use is 1678 AD to 2262 AD. (GH4041)
DataFrame.to_stata will now check data for compatibility with Stata data types and will upcast when
needed. When it is not possible to losslessly upcast, a warning is issued (GH6327)
DataFrame.to_stata and StataWriter will accept keyword arguments time_stamp and data_label
which allow the time stamp and dataset label to be set when creating a file. (GH6545)
pandas.io.gbq now handles reading unicode strings properly. (GH5940)
Holidays Calendars are now available and can be used with the CustomBusinessDay offset (GH6719)
Float64Index is now backed by a float64 dtype ndarray instead of an object dtype array (GH6471).
Implemented Panel.pct_change (GH6904)
Added how option to rolling-moment functions to dictate how to handle resampling; rolling_max() defaults to max, rolling_min() defaults to min, and all others default to mean (GH6297)
121
Date
13:00:00
13:05:00
20:00:00
10:00:00
20:00:00
10:00:00
2013-10-04
2013-10-15
2013-09-05
2013-11-02
2013-10-07
2013-09-05
PayDay
00:00:00
13:05:00
20:00:00
10:00:00
20:00:00
10:00:00
Quantity
1
3
5
1
8
1
122
0.755414
0.215269
0.841009
-1.445810
-1.401973
-0.100918
2013-01-01 15:00
-0.548242
...
2013-01-05 06:00
-0.379811
2013-01-05 07:00
0.702562
2013-01-05 08:00
-0.850346
2013-01-05 09:00
1.176812
2013-01-05 10:00
-0.524336
2013-01-05 11:00
0.700908
2013-01-05 12:00
0.984188
Freq: H, dtype: float64
In [82]: ps['2013-01-02']
Out[82]:
2013-01-02 00:00
-0.208499
2013-01-02 01:00
1.033801
2013-01-02 02:00
-2.400454
2013-01-02 03:00
2.030604
2013-01-02 04:00
-1.142631
2013-01-02 05:00
0.211883
2013-01-02 06:00
0.704721
...
2013-01-02 17:00
0.464392
2013-01-02 18:00
-3.563517
2013-01-02 19:00
1.321106
2013-01-02 20:00
0.152631
2013-01-02 21:00
0.164530
2013-01-02 22:00
-0.430096
2013-01-02 23:00
0.767369
Freq: H, dtype: float64
read_excel can now read milliseconds in Excel dates and times with xlrd >= 0.9.3. (GH5945)
pd.stats.moments.rolling_var now uses Welfords method for increased numerical stability
(GH6817)
pd.expanding_apply and pd.rolling_apply now take args and kwargs that are passed on to the func (GH6289)
DataFrame.rank() now has a percentage rank option (GH5971)
Series.rank() now has a percentage rank option (GH5971)
Series.rank() and DataFrame.rank() now accept method=dense for ranks without gaps
(GH6514)
Support passing encoding with xlwt (GH3710)
Refactor Block classes removing Block.items attributes to avoid duplication in item handling (GH6745,
GH6988).
Testing statements updated to use specialized asserts (GH6175)
1.9.12 Performance
Performance improvement when
DatetimeConverter (GH6636)
converting
DatetimeIndex
to
floating
ordinals
using
123
Improve performance of DataFrame construction with certain offsets, by removing faulty caching (e.g. MonthEnd,BusinessMonthEnd), (GH6479)
Improve performance of CustomBusinessDay (GH6584)
improve performance of slice indexing on Series with string keys (GH6341, GH6372)
Performance improvement for DataFrame.from_records when reading a specified number of rows from
an iterable (GH6700)
Performance improvements in timedelta conversions for integer dtypes (GH6754)
Improved performance of compatible pickles (GH6899)
Improve performance in certain reindexing operations by optimizing take_2d (GH6749)
GroupBy.count() is now implemented in Cython and is much faster for large numbers of groups (GH7016).
1.9.13 Experimental
There are no experimental changes in 0.14.0
124
Bug in TimeGrouper/resample when presented with a non-monotonic DatetimeIndex that would return invalid
results. (GH4161)
Bug in index name propogation in TimeGrouper/resample (GH4161)
TimeGrouper has a more compatible API to the rest of the groupers (e.g. groups was missing) (GH3881)
Bug in multiple grouping with a TimeGrouper depending on target column order (GH6764)
Bug in pd.eval when parsing strings with possible tokens like & (GH6351)
Bug correctly handle placements of -inf in Panels when dividing by integer 0 (GH6178)
DataFrame.shift with axis=1 was raising (GH6371)
Disabled clipboard tests until release time (run locally with nosetests -A disabled) (GH6048).
Bug in DataFrame.replace() when passing a nested dict that contained keys not in the values to be
replaced (GH6342)
str.match ignored the na flag (GH6609).
Bug in take with duplicate columns that were not consolidated (GH6240)
Bug in interpolate changing dtypes (GH6290)
Bug in Series.get, was using a buggy access method (GH6383)
Bug in hdfstore queries of the form where=[(date, >=, datetime(2013,1,1)),
(date, <=, datetime(2014,1,1))] (GH6313)
Bug in DataFrame.dropna with duplicate indices (GH6355)
Regression in chained getitem indexing with embedded list-like from 0.12 (GH6394)
Float64Index with nans not comparing correctly (GH6401)
eval/query expressions with strings containing the @ character will now work (GH6366).
Bug in Series.reindex when specifying a method with some nan values was inconsistent (noted on a
resample) (GH6418)
Bug in DataFrame.replace() where nested dicts were erroneously depending on the order of dictionary
keys and values (GH5338).
Perf issue in concatting with empty objects (GH3259)
Clarify sorting of sym_diff on Index objects with NaN values (GH6444)
Regression in MultiIndex.from_product with a DatetimeIndex as input (GH6439)
Bug in str.extract when passed a non-default index (GH6348)
Bug in str.split when passed pat=None and n=1 (GH6466)
Bug
in
io.data.DataReader
when
data_source="famafrench" (GH6460)
passed
"F-F_Momentum_Factor"
and
125
126
Bug in Makefile where it didnt remove Cython generated C files with make clean (GH6768)
Bug with numpy < 1.7.2 when reading long strings from HDFStore (GH6166)
Bug in DataFrame._reduce where non bool-like (0/1) integers were being coverted into bools. (GH6806)
Regression from 0.13 with fillna and a Series on datetime-like (GH6344)
Bug in adding np.timedelta64 to DatetimeIndex with timezone outputs incorrect results (GH6818)
Bug in DataFrame.replace() where changing a dtype through replacement would only replace the first
occurrence of a value (GH6689)
Better error message when passing a frequency of MS in Period construction (GH5332)
Bug in Series.__unicode__ when max_rows=None and the Series has more than 1000 rows. (GH6863)
Bug in groupby.get_group where a datetlike wasnt always accepted (GH5267)
Bug in groupBy.get_group created by TimeGrouper raises AttributeError (GH6914)
Bug in DatetimeIndex.tz_localize and DatetimeIndex.tz_convert converting NaT incorrectly (GH5546)
Bug in arithmetic operations affecting NaT (GH6873)
Bug in Series.str.extract where the resulting Series from a single group match wasnt renamed to
the group name
Bug in DataFrame.to_csv where setting index=False ignored the header kwarg (GH6186)
Bug in DataFrame.plot and Series.plot, where the legend behave inconsistently when plotting to the
same axes repeatedly (GH6678)
Internal tests for patching __finalize__ / bug in merge not finalizing (GH6923, GH6927)
accept TextFileReader in concat, which was affecting a common user idiom (GH6583)
Bug in C parser with leading whitespace (GH3374)
Bug in C parser with delim_whitespace=True and \r-delimited lines
Bug in python parser with explicit multi-index in row following column header (GH6893)
Bug in Series.rank and DataFrame.rank that caused small floats (<1e-13) to all receive the same rank
(GH6886)
Bug in DataFrame.apply with functions that used *args or **kwargs and returned an empty result
(GH6952)
Bug in sum/mean on 32-bit platforms on overflows (GH6915)
Moved Panel.shift to NDFrame.slice_shift and fixed to respect multiple dtypes. (GH6959)
Bug in enabling subplots=True in DataFrame.plot only has single column raises TypeError, and
Series.plot raises AttributeError (GH6951)
Bug in DataFrame.plot draws unnecessary axes when enabling subplots and kind=scatter
(GH6951)
Bug in read_csv from a filesystem with non-utf-8 encoding (GH6807)
Bug in iloc when setting / aligning (GH6766)
Bug causing UnicodeEncodeError when get_dummies called with unicode values and a prefix (GH6885)
Bug in timeseries-with-frequency plot cursor display (GH5453)
Bug surfaced in groupby.plot when using a Float64Index (GH7025)
127
Stopped tests from failing if options data isnt able to be downloaded from Yahoo (GH7034)
Bug in parallel_coordinates and radviz where reordering of class column caused possible color/class
mismatch (GH6956)
Bug in radviz and andrews_curves where multiple values of color were being passed to plotting method
(GH6956)
Bug in Float64Index.isin() where containing nan s would make indices claim that they contained all
the things (GH7066).
Bug in DataFrame.boxplot where it failed to use the axis passed as the ax argument (GH3578)
Bug in the XlsxWriter and XlwtWriter implementations that resulted in datetime columns being formatted without the time (GH7075) were being passed to plotting method
read_fwf() treats None in colspec like regular python slices. It now reads from the beginning or until the
end of the line when colspec contains a None (previously raised a TypeError)
Bug in cache coherence with chained indexing and slicing; add _is_view property to NDFrame to correctly
predict views; mark is_copy on xs only if its an actual copy (and not a view) (GH7084)
Bug in DatetimeIndex creation from string ndarray with dayfirst=True (GH5917)
Bug in MultiIndex.from_arrays created from DatetimeIndex doesnt preserve freq and tz
(GH7090)
Bug in unstack raises ValueError when MultiIndex contains PeriodIndex (GH4342)
Bug in boxplot and hist draws unnecessary axes (GH6769)
Regression in groupby.nth() for out-of-bounds indexers (GH6621)
Bug in quantile with datetime values (GH6965)
Bug in Dataframe.set_index, reindex and pivot dont preserve DatetimeIndex and
PeriodIndex attributes (GH3950, GH5878, GH6631)
Bug in MultiIndex.get_level_values doesnt preserve DatetimeIndex and PeriodIndex attributes (GH7092)
Bug in Groupby doesnt preserve tz (GH3950)
Bug in PeriodIndex partial string slicing (GH6716)
Bug in the HTML repr of a truncated Series or DataFrame not showing the class name with the large_repr set
to info (GH7105)
Bug in DatetimeIndex specifying freq raises ValueError when passed value is too short (GH7098)
Fixed a bug with the info repr not honoring the display.max_info_columns setting (GH6939)
Bug PeriodIndex string slicing with out of bounds values (GH5407)
Fixed a memory error in the hashtable implementation/factorizer on resizing of large tables (GH7157)
Bug in isnull when applied to 0-dimensional object arrays (GH7176)
Bug in query/eval where global constants were not looked up correctly (GH7178)
Bug in recognizing out-of-bounds positional list indexers with iloc and a multi-axis tuple indexer (GH7189)
Bug in setitem with a single value, multi-index and integer indices (GH7190, GH7218)
Bug in expressions evaluation with reversed ops, showing in series-dataframe ops (GH7198, GH7192)
Bug in multi-axis indexing with > 2 ndim and a multi-index (GH7199)
128
Fix a bug where invalid eval/query operations would blow the stack (GH5198)
129
Add show_dimensions display option for the new DataFrame repr to control whether the dimensions print.
In [14]: df = DataFrame([[1, 2], [3, 4]])
In [15]: pd.set_option('show_dimensions', False)
In [16]: df
Out[16]:
0 1
0 1 2
1 3 4
In [17]: pd.set_option('show_dimensions', True)
In [18]: df
Out[18]:
0 1
0 1 2
130
[2 rows x 2 columns]
The ArrayFormatter for datetime and timedelta64 now intelligently limit precision based on the
values in the array (GH3401)
Previously output might look like:
age
today
diff
0 2001-01-01 00:00:00 2013-04-19 00:00:00 4491 days, 00:00:00
1 2004-06-01 00:00:00 2013-04-19 00:00:00 3244 days, 00:00:00
s.str.get_dummies(sep='|')
c
0
0
0
1
[4 rows x 3 columns]
Added the NDFrame.equals() method to compare if two NDFrames are equal have equal axes, dtypes, and
values. Added the array_equivalent function to compare if two ndarrays are equal. NaNs in identical
locations are treated as equal. (GH5283) See also the docs for a motivating example.
In [25]: df = DataFrame({'col':['foo', 0, np.nan]})
In [26]: df2 = DataFrame({'col':[np.nan, 0, 'foo']}, index=[2,1,0])
131
In [27]: df.equals(df2)
Out[27]: False
In [28]: df.equals(df2.sort())
Out[28]: True
In [29]: import pandas.core.common as com
In [30]: com.array_equivalent(np.array([0, np.nan]), np.array([0, np.nan]))
Out[30]: True
In [31]: np.array_equal(np.array([0, np.nan]), np.array([0, np.nan]))
Out[31]: False
DataFrame.apply will use the reduce argument to determine whether a Series or a DataFrame
should be returned when the DataFrame is empty (GH6007).
Previously, calling DataFrame.apply an empty DataFrame would return either a DataFrame if there
were no columns, or the function being applied would be called with an empty Series to guess whether a
Series or DataFrame should be returned:
In [32]: def applied_func(col):
....:
print("Apply function being called with: ", col)
....:
return col.sum()
....:
In [33]: empty = DataFrame(columns=['a', 'b'])
In [34]: empty.apply(applied_func)
('Apply function being called with: ', Series([], dtype: float64))
Out[34]:
a
NaN
b
NaN
dtype: float64
Now, when apply is called on an empty DataFrame: if the reduce argument is True a Series will
returned, if it is False a DataFrame will be returned, and if it is None (the default) the function being
applied will be called with an empty series to try and guess the return type.
In [35]: empty.apply(applied_func, reduce=True)
Out[35]:
a
NaN
b
NaN
dtype: float64
In [36]: empty.apply(applied_func, reduce=False)
Out[36]:
Empty DataFrame
Columns: [a, b]
Index: []
[0 rows x 2 columns]
132
1.10.4 Deprecations
There are no deprecations of prior behavior in 0.13.1
1.10.5 Enhancements
pd.read_csv and pd.to_datetime learned a new infer_datetime_format keyword which greatly
improves parsing perf in many cases. Thanks to @lexual for suggesting and @danbirken for rapidly implementing. (GH5490, GH6021)
If parse_dates is enabled and this flag is set, pandas will attempt to infer the format of the datetime strings
in the columns, and if it can be inferred, switch to a faster method of parsing them. In some cases this can
increase the parsing speed by ~5-10x.
# Try to infer the format for the index column
df = pd.read_csv('foo.csv', index_col=0, parse_dates=True,
infer_datetime_format=True)
date_format and datetime_format keywords can now be specified when writing to excel files
(GH4133)
MultiIndex.from_product convenience function for creating a MultiIndex from the cartesian product of
a set of iterables (GH6055):
In [37]: shades = ['light', 'dark']
In [38]: colors = ['red', 'green', 'blue']
In [39]: MultiIndex.from_product([shades, colors], names=['shade', 'color'])
Out[39]:
MultiIndex(levels=[[u'dark', u'light'], [u'blue', u'green', u'red']],
labels=[[1, 1, 1, 0, 0, 0], [2, 1, 0, 2, 1, 0]],
names=[u'shade', u'color'])
133
This is equivalent to
In [46]: panel.sum('major_axis')
Out[46]:
ItemA
ItemB
ItemC
A 0.379252 -3.696907 3.709335
B 0.923558 0.504242 4.656781
C -3.118269 -1.545718 3.188329
D -1.979310 -0.758060 -1.436483
[4 rows x 3 columns]
A transformation operation that returns a Panel, but is computing the z-score across the major_axis
In [47]: result = panel.apply(
....:
lambda x: (x-x.mean())/x.std(),
....:
axis='major_axis')
....:
In [48]: result
Out[48]:
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 5 (major_axis) x 4 (minor_axis)
Items axis: ItemA to ItemC
Major_axis axis: 2000-01-03 00:00:00 to 2000-01-07 00:00:00
Minor_axis axis: A to D
In [49]: result['ItemA']
Out[49]:
A
B
C
D
2000-01-03 1.004994 -1.166509 -0.535027 0.350970
2000-01-04 1.045875 -0.036892 1.393532 1.536326
2000-01-05 -0.170198 -0.334055 -1.037810 -0.970374
2000-01-06 -0.718186 1.588611 -0.492880 -0.736422
2000-01-07 -1.162486 -0.051156 0.672185 -0.180500
134
[5 rows x 4 columns]
D
-0.157547
0.760706
-0.015033
-1.140165
-1.123913
[5 rows x 4 columns]
D
-0.157547
0.760706
-0.015033
-1.140165
-1.123913
[5 rows x 4 columns]
1.10.6 Performance
Performance improvements for 0.13.1
Series datetime/timedelta binary operations (GH5801)
135
1.10.7 Experimental
There are no experimental changes in 0.13.1
136
All division with NDFrame objects is now truedivision, regardless of the future import. This means that operating on pandas objects will by default use floating point division, and return a floating point dtype. You can use
// and floordiv to do integer division.
Integer division
In [3]: arr = np.array([1, 2, 3, 4])
In [4]: arr2 = np.array([5, 3, 2, 1])
In [5]: arr / arr2
Out[5]: array([0, 0, 1, 4])
In [6]: Series(arr) // Series(arr2)
Out[6]:
0
0
1
0
137
2
1
3
4
dtype: int64
True Division
In [7]: pd.Series(arr) / pd.Series(arr2) # no future import required
Out[7]:
0
0.200000
1
0.666667
2
1.500000
3
4.000000
dtype: float64
Added the .bool() method to NDFrame objects to facilitate evaluating of single-element boolean Series:
In [1]: Series([True]).bool()
Out[1]: True
In [2]: Series([False]).bool()
Out[2]: False
In [3]: DataFrame([[True]]).bool()
Out[3]: True
In [4]: DataFrame([[False]]).bool()
Out[4]: False
All non-Index NDFrames (Series, DataFrame, Panel, Panel4D, SparsePanel, etc.), now support the
entire set of arithmetic operators and arithmetic flex methods (add, sub, mul, etc.). SparsePanel does not
support pow or mod with non-scalars. (GH3765)
Series and DataFrame now have a mode() method to calculate the statistical mode(s) by axis/Series.
(GH5367)
Chained assignment will now by default warn if the user is assigning to a copy. This can be changed with the
option mode.chained_assignment, allowed options are raise/warn/None. See the docs.
In [5]: dfc = DataFrame({'A':['aaa','bbb','ccc'],'B':[1,2,3]})
In [6]: pd.set_option('chained_assignment','warn')
138
dfc
B
1
2
3
[3 rows x 2 columns]
Series.argmin and Series.argmax are now aliased to Series.idxmin and Series.idxmax. These return the i
min or max element respectively. Prior to 0.13.0 these would return the position of the min / max element.
(GH6214)
1.11.3 Deprecations
Deprecated in 0.13.0
deprecated iterkv, which will be removed in a future release (this was an alias of iteritems used to bypass
2to3s changes). (GH4384, GH4375, GH4372)
deprecated the string method match, whose role is now performed more idiomatically by extract. In a
future release, the default behavior of match will change to become analogous to contains, which returns
a boolean indexer. (Their distinction is strictness: match relies on re.match while contains relies on
re.search.) In this release, the deprecated behavior is the default, but the new behavior is available through
the keyword argument as_indexer=True.
139
dfi
C
0
2
4
[3 rows x 3 columns]
140
1
2
3
2
4
5
3
5
5
2
4
5
[4 rows x 3 columns]
A Panel setting operation on an arbitrary axis aligns the input to the Panel
In [20]: p = pd.Panel(np.arange(16).reshape(2,4,2),
....:
items=['Item1','Item2'],
....:
major_axis=pd.date_range('2001/1/12',periods=4),
....:
minor_axis=['A','B'],dtype='float64')
....:
In [21]: p
Out[21]:
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 4 (major_axis) x 2 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2001-01-12 00:00:00 to 2001-01-15 00:00:00
Minor_axis axis: A to B
In [22]: p.loc[:,:,'C'] = Series([30,32],index=p.items)
In [23]: p
Out[23]:
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 4 (major_axis) x 3 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2001-01-12 00:00:00 to 2001-01-15 00:00:00
Minor_axis axis: A to C
In [24]: p.loc[:,:,'C']
Out[24]:
Item1 Item2
2001-01-12
30
32
2001-01-13
30
32
2001-01-14
30
32
2001-01-15
30
32
[4 rows x 2 columns]
141
In [28]: s
Out[28]:
1.5
0
2.0
1
3.0
2
4.5
3
5.0
4
dtype: int64
Scalar selection for [],.ix,.loc will always be label based. An integer will match an equal float index (e.g.
3 is equivalent to 3.0)
In [29]: s[3]
Out[29]: 2
In [30]: s.ix[3]
Out[30]: 2
In [31]: s.loc[3]
Out[31]: 2
142
dtype: int64
In [38]: s.loc[2.1:4.6]
Out[38]:
3.0
2
4.5
3
dtype: int64
Indexing on other index types are preserved (and positional fallback for [],ix), with the exception, that floating
point slicing on indexes on non Float64Index will now raise a TypeError.
In [1]: Series(range(5))[3.5]
TypeError: the label [3.5] is not a proper indexer for this index type (Int64Index)
In [1]: Series(range(5))[3.5:4.5]
TypeError: the slice start [3.5] is not a proper indexer for this index type (Int64Index)
Using a scalar float indexer will be deprecated in a future version, but is allowed for now.
In [3]: Series(range(5))[3.0]
Out[3]: 3
143
2013-01-01
2013-01-03
2013-01-04
2013-01-05
2013-01-06
2013-01-07
2013-01-09
2013-01-10
1.126386
0.581073
-0.275774
-1.392054
-0.881047
-1.407085
1.529401
0.299071
0.247112
2.763844
0.500483
1.153922
0.295080
0.126781
0.205455
1.076541
0.121172 0.298984
0.399325 0.668488
0.863065 -1.051628
1.181944 0.391371
1.863801 -1.712274
0.003760 -1.268994
0.313013 0.866521
0.363177 1.893680
[8 rows x 4 columns]
the format keyword now replaces the table keyword; allowed values are fixed(f) or table(t) the
same defaults as prior < 0.13.0 remain, e.g. put implies fixed format and append implies table format.
This default format can be set as an option by setting io.hdf.default_format.
In [44]: path = 'test.h5'
In [45]: df = DataFrame(randn(10,2))
In [46]: df.to_hdf(path,'df_table',format='table')
In [47]: df.to_hdf(path,'df_table2',append=True)
In [48]: df.to_hdf(path,'df_fixed')
In [49]: with get_store(path) as store:
....:
print(store)
....:
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df_fixed
frame
(shape->[10,2])
/df_table
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
/df_table2
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
144
In [56]: store1
Out[56]:
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
In [57]: store2
Out[57]:
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
/df2
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
In [58]: store1.close()
In [59]: store2
Out[59]:
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
/df2
frame_table (typ->appendable,nrows->10,ncols->2,indexers->[index])
In [60]: store2.close()
In [61]: store2
Out[61]:
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
File is CLOSED
removed the _quiet attribute, replace by a DuplicateWarning if retrieving duplicate rows from a table
(GH4367)
removed the warn argument from open. Instead a PossibleDataLossError exception will be raised if
you try to use mode=w with an OPEN file handle (GH4367)
allow a passed locations array or mask as a where condition (GH4467). See the docs for an example.
add the keyword dropna=True to append to change whether ALL nan rows are not written to the store
(default is True, ALL nan rows are NOT written), also settable via the option io.hdf.dropna_table
(GH4625)
pass thru store creation arguments; can be used to support in-memory stores
145
To get the info view, call DataFrame.info(). If you prefer the info view as the repr for large DataFrames, you
can set this by running set_option(display.large_repr, info).
1.11.8 Enhancements
df.to_clipboard() learned a new excel keyword that lets you paste df data directly into excel (enabled
by default). (GH5070).
read_html now raises a URLError instead of catching and raising a ValueError (GH4303, GH4305)
Added a test for read_clipboard() and to_clipboard() (GH4282)
Clipboard functionality now works with PySide (GH4282)
Added a more informative error message when plot arguments contain overlapping color and style arguments
(GH4402)
to_dict now takes records as a possible outtype. Returns an array of column-keyed dictionaries. (GH4936)
NaN handing in get_dummies (GH4446) with dummy_na
# previously, nan was erroneously counted as 2 here
# now it is not counted at all
In [62]: get_dummies([1, 2, np.nan])
Out[62]:
1 2
0 1 0
1 0 1
2 0 0
[3 rows x 2 columns]
# unless requested
In [63]: get_dummies([1, 2, np.nan], dummy_na=True)
Out[63]:
1
2
NaN
0
1
0
0
1
0
1
0
2
0
0
1
[3 rows x 3 columns]
146
Using the new top-level to_timedelta, you can convert a scalar or array from the standard timedelta format
(produced by to_csv) into a timedelta type (np.timedelta64 in nanoseconds).
In [64]: to_timedelta('1 days 06:05:01.00003')
Out[64]: Timedelta('1 days 06:05:01.000030')
In [65]: to_timedelta('15.5us')
Out[65]: Timedelta('0 days 00:00:00.000015')
In [67]: to_timedelta(np.arange(5),unit='s')
Out[67]: TimedeltaIndex(['00:00:00', '00:00:01', '00:00:02', '00:00:03', '00:00:04'], dtype='tim
In [68]: to_timedelta(np.arange(5),unit='d')
Out[68]: TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'], dtype='timedelta64[n
147
2
2678703
3
NaN
dtype: float64
In [77]: td.astype('timedelta64[s]')
Out[77]:
0
2678400
1
2678400
2
2678703
3
NaN
dtype: float64
148
plot(kind=kde) now accepts the optional parameters bw_method and ind, passed to
scipy.stats.gaussian_kde() (for scipy >= 0.11.0) to set the bandwidth, and to gkde.evaluate() to specify the indices at which it is evaluated, respectively. See scipy docs. (GH4298)
DataFrame constructor now accepts a numpy masked record array (GH3478)
The new vectorized string method extract return regular expression matches more conveniently.
In [86]: Series(['a1', 'b2', 'c3']).str.extract('[ab](\d)')
Out[86]:
0
1
1
2
2
NaN
dtype: object
Elements that do not match return NaN. Extracting a regular expression with more than one group returns a
DataFrame with one column per group.
In [87]: Series(['a1', 'b2', 'c3']).str.extract('([ab])(\d)')
Out[87]:
0
1
0
a
1
1
b
2
2 NaN NaN
[3 rows x 2 columns]
Elements that do not match return a row of NaN. Thus, a Series of messy strings can be converted into a likeindexed Series or DataFrame of cleaned-up or more useful strings, without necessitating get() to access tuples
or re.match objects.
Named groups like
In [88]: Series(['a1', 'b2', 'c3']).str.extract(
....:
'(?P<letter>[ab])(?P<digit>\d)')
....:
Out[88]:
letter digit
0
a
1
1
b
2
2
NaN
NaN
[3 rows x 2 columns]
149
NaN
[3 rows x 2 columns]
A new method, isin for DataFrames, which plays nicely with boolean indexing. The argument to isin, what
were comparing the DataFrame to, can be a DataFrame, Series, dict, or array of values. See the docs for more.
To get the rows where any of the conditions are met:
In [94]: dfi = DataFrame({'A': [1, 2, 3, 4], 'B': ['a', 'b', 'f', 'n']})
In [95]: dfi
Out[95]:
A B
0 1 a
1 2 b
2 3 f
3 4 n
[4 rows x 2 columns]
In [96]: other = DataFrame({'A': [1, 3, 3, 7], 'B': ['e', 'f', 'f', 'e']})
In [97]: mask = dfi.isin(other)
In [98]: mask
150
Out[98]:
A
0
True
1 False
2
True
3 False
B
False
False
True
False
[4 rows x 2 columns]
In [99]: dfi[mask.any(1)]
Out[99]:
A B
0 1 a
2 3 f
[2 rows x 2 columns]
tz_localize can infer a fall daylight savings transition based on the structure of the unlocalized data
(GH4230), see the docs
DatetimeIndex is now in the API documentation, see the docs
json_normalize() is a new method to allow you to create a flat table from semi-structured JSON data. See
the docs (GH1067)
Added PySide support for the qtpandas DataFrameModel and DataFrameWidget.
Python csv parser now supports usecols (GH4335)
Frequencies gained several new offsets:
LastWeekOfMonth (GH4637)
FY5253, and FY5253Quarter (GH4511)
DataFrame has a new interpolate method, similar to Series (GH4434, GH1892)
In [100]: df = DataFrame({'A': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
.....:
'B': [.25, np.nan, np.nan, 4, 12.2, 14.4]})
.....:
In [101]: df.interpolate()
Out[101]:
A
B
0 1.0
0.25
1 2.1
1.50
2 3.4
2.75
3 4.7
4.00
4 5.6 12.20
5 6.8 14.40
[6 rows x 2 columns]
151
Additionally, the method argument to interpolate has been expanded to include nearest,
zero, slinear, quadratic, cubic, barycentric, krogh,
piecewise_polynomial, pchip, polynomial, spline The new methods require scipy. Consult the Scipy reference guide and documentation for more information about when the various
methods are appropriate. See the docs.
Interpolate now also accepts a limit keyword argument. This works similar to fillnas limit:
In [102]: ser = Series([1, 3, np.nan, np.nan, np.nan, 11])
In [103]: ser.interpolate(limit=2)
Out[103]:
0
1
1
3
2
5
3
7
4
NaN
5
11
dtype: float64
2 : "c"},
2 : "f"},
2 : .7},
2 : .1},
np.random.randn(3)))
B1970
2.5
1.2
0.7
B1980
X
3.2 -1.085631
1.3 0.997345
0.1 0.282978
id
0
1
2
[3 rows x 6 columns]
In [108]: wide_to_long(df, ["A", "B"], i="id", j="year")
Out[108]:
X A
B
id year
0 1970 -1.085631 a 2.5
1 1970 0.997345 b 1.2
2 1970 0.282978 c 0.7
0 1980 -1.085631 d 3.2
1 1980 0.997345 e 1.3
2 1980 0.282978 f 0.1
[6 rows x 3 columns]
to_csv now takes a date_format keyword argument that specifies how output datetime objects should
be formatted. Datetimes encountered in the index, columns, and values will all have this formatting applied.
(GH4313)
152
1.11.9 Experimental
The new eval() function implements expression evaluation using numexpr behind the scenes. This results
in large speedups for complicated expressions involving large DataFrames/Series. For example,
In [109]: nrows, ncols = 20000, 100
In [110]: df1, df2, df3, df4 = [DataFrame(randn(nrows, ncols))
.....:
for _ in range(4)]
.....:
# eval with NumExpr backend
In [111]: %timeit pd.eval('df1 + df2 + df3 + df4')
100 loops, best of 3: 14.9 ms per loop
# pure Python evaluation
In [112]: %timeit df1 + df2 + df3 + df4
10 loops, best of 3: 22.8 ms per loop
query() method has been added that allows you to select elements of a DataFrame using a natural query
syntax nearly identical to Python syntax. For example,
In [115]: n = 20
In [116]: df = DataFrame(np.random.randint(n, size=(n, 3)), columns=['a', 'b', 'c'])
In [117]: df.query('a < b < c')
Out[117]:
a
b
c
11 1
5
8
15 8 16 19
[2 rows x 3 columns]
153
selects all the rows of df where a < b < c evaluates to True. For more details see the the docs.
pd.read_msgpack() and pd.to_msgpack() are now a supported method of serialization of arbitrary
pandas (and python objects) in a lightweight portable binary format. See the docs
Warning: Since this is an EXPERIMENTAL LIBRARY, the storage format may not be stable until a future
release.
In [118]: df = DataFrame(np.random.rand(5,2),columns=list('AB'))
In [119]: df.to_msgpack('foo.msg')
In [120]: pd.read_msgpack('foo.msg')
Out[120]:
A
B
0 0.251082 0.017357
1 0.347915 0.929879
2 0.546233 0.203368
3 0.064942 0.031722
4 0.355309 0.524575
[5 rows x 2 columns]
In [121]: s = Series(np.random.rand(5),index=date_range('20130101',periods=5))
In [122]: pd.to_msgpack('foo.msg', df, s)
In [123]: pd.read_msgpack('foo.msg')
Out[123]:
[
A
B
0 0.251082 0.017357
1 0.347915 0.929879
2 0.546233 0.203368
3 0.064942 0.031722
4 0.355309 0.524575
[5 rows x 2 columns], 2013-01-01
2013-01-02
0.227025
2013-01-03
0.383282
2013-01-04
0.193225
2013-01-05
0.110977
Freq: D, dtype: float64]
0.022321
154
2013-01-04
0.193225
2013-01-05
0.110977
Freq: D, dtype: float64
pandas.io.gbq provides a simple way to extract from, and load data into, Googles BigQuery Data Sets by
way of pandas DataFrames. BigQuery is a high performance SQL-like database service, useful for performing
ad-hoc queries against extremely large datasets. See the docs
from pandas.io import gbq
#
#
#
#
-53.336667
-49.837500
-77.926087
-82.892858
-92.378261
-77.703334
-87.821428
-89.431999
-86.611112
-78.209677
-50.125000
-50.332258
Mean Temp
39.827892
43.685219
48.708355
55.070087
61.428117
65.858888
68.169663
68.614215
63.436935
56.880838
48.861228
42.286879
Max Temp
89.770968
93.437932
96.099998
97.317240
102.042856
102.900000
106.510714
105.500000
107.142856
92.103333
94.996428
94.396774
155
Warning:
To use this module, you will need a BigQuery account.
See
<https://cloud.google.com/products/big-query> for details.
As of 10/10/13, there is a bug in Googles API preventing result sets from being larger than 100,000 rows.
A patch is scheduled for the week of 10/14/13.
156
Numpy Usage
In [126]: np.ones_like(s)
Out[126]: array([1, 1, 1, 1], dtype=int64)
In [127]: np.diff(s)
Out[127]: array([1, 1, 1], dtype=int64)
In [128]: np.where(s>1,s,np.nan)
Out[128]: array([ nan,
2.,
3.,
4.])
Pandonic Usage
In [129]: Series(1,index=s.index)
Out[129]:
0
1
1
1
2
1
3
1
dtype: int64
In [130]: s.diff()
Out[130]:
0
NaN
1
1
2
1
3
1
dtype: float64
In [131]: s.where(s>1)
Out[131]:
0
NaN
1
2
2
3
3
4
dtype: float64
Passing a Series directly to a cython function expecting an ndarray type will no long work directly, you
must pass Series.values, See Enhancing Performance
Series(0.5) would previously return the scalar 0.5, instead this will return a 1-element Series
This change breaks rpy2<=2.3.8. an Issue has been opened against rpy2 and a workaround is detailed in
GH5698. Thanks @JanSchulz.
Pickle compatibility is preserved for pickles created prior to 0.13.
pd.read_pickle, see Pickling.
157
* __iter__,keys,__contains__,__len__,__neg__,__invert__
* convert_objects,as_blocks,as_matrix,values
* __getstate__,__setstate__ (compat remains in frame/panel)
* __getattr__,__setattr__
* _indexed_same,reindex_like,align,where,mask
* fillna,replace (Series replace is now consistent with DataFrame)
* filter (also added axis argument to selectively filter on a different axis)
* reindex,reindex_axis,take
* truncate (moved to become part of NDFrame)
These are API changes which make Panel more consistent with DataFrame
swapaxes on a Panel with the same axes specified now return a copy
support attribute access for setting
filter supports the same API as the original DataFrame filter
Reindex called with no arguments will now return a copy of the input object
TimeSeries is now an alias for Series. the property is_time_series can be used to distinguish (if
desired)
Refactor of Sparse objects to use BlockManager
Created a new block type in internals, SparseBlock, which can hold multi-dtypes and is nonconsolidatable. SparseSeries and SparseDataFrame now inherit more methods from there hierarchy (Series/DataFrame), and no longer inherit from SparseArray (which instead is the object of
the SparseBlock)
Sparse suite now supports integration with non-sparse data. Non-float sparse data is supportable (partially
implemented)
Operations on sparse structures within DataFrames should preserve sparseness, merging type operations
will convert to dense (and back to sparse), so might be somewhat inefficient
enable setitem on SparseSeries for boolean/integer/slices
SparsePanels implementation is unchanged (e.g. not using BlockManager, needs work)
added ftypes method to Series/DataFrame, similar to dtypes, but indicates if the underlying is sparse/dense
(as well as the dtype)
All NDFrame objects can now use __finalize__() to specify various values to propagate to new objects
from an existing one (e.g. name in Series will follow more automatically now)
Internal type checking is now done via a suite of generated classes, allowing isinstance(value, klass)
without having to directly import the klass, courtesy of @jtratner
Bug in Series update where the parent frame is not updating its cache based on changes (GH4080) or types
(GH3217), fillna (GH3386)
Indexing with dtype conversions fixed (GH4463, GH4204)
Refactor Series.reindex to core/generic.py (GH4604, GH4618), allow method= in reindexing on a Series to work
Series.copy no longer accepts the order parameter and is now consistent with NDFrame copy
158
Refactor rename methods to core/generic.py; fixes Series.rename for (GH4605), and adds rename with
the same signature for Panel
Refactor clip methods to core/generic.py (GH4798)
Refactor of _get_numeric_data/_get_bool_data to core/generic.py, allowing Series/Panel functionality
Series (for index) / Panel (for items) now allow attribute access to its elements (GH1903)
In [132]: s = Series([1,2,3],index=list('abc'))
In [133]: s.b
Out[133]: 2
In [134]: s.a = 5
In [135]: s
Out[135]:
a
5
b
2
c
3
dtype: int64
159
read_clipboard
The corresponding writer functions are object methods that are accessed like df.to_csv()
to_csv
to_excel
to_hdf
to_sql
to_json
to_html
to_stata
to_clipboard
Fix modulo and integer division on Series,DataFrames to act similary to float dtypes to return np.nan
or np.inf as appropriate (GH3590). This correct a numpy bug that treats integer and float dtypes
differently.
In [1]: p = DataFrame({ 'first' : [4,5,8], 'second' : [0,0,3] })
In [2]: p % 0
Out[2]:
first second
0
NaN
NaN
1
NaN
NaN
2
NaN
NaN
[3 rows x 2 columns]
In [3]: p % p
Out[3]:
first second
0
0
NaN
1
0
NaN
2
0
0
[3 rows x 2 columns]
In [4]: p / p
Out[4]:
first second
0
1
NaN
1
1
NaN
2
1
1
[3 rows x 2 columns]
In [5]: p / 0
Out[5]:
first second
0
inf
NaN
1
inf
NaN
2
inf
inf
[3 rows x 2 columns]
160
Add squeeze keyword to groupby to allow reduction from DataFrame -> Series if groups are unique. This
is a Regression from 0.10.1. We are reverting back to the prior behavior. This means groupby will return the
same shaped objects whether the groups are unique or not. Revert this issue (GH2893) with (GH3596).
In [6]: df2 = DataFrame([{"val1": 1, "val2" : 20}, {"val1":1, "val2": 19},
...:
{"val1":1, "val2": 27}, {"val1":1, "val2": 12}])
...:
In [7]: def func(dataf):
...:
return dataf["val2"]
...:
- dataf["val2"].mean()
Raise on iloc when boolean indexing with a label based indexer mask e.g. a boolean Series, even with integer
labels, will raise. Since iloc is purely positional based, the labels on the Series are not alignable (GH3631)
This case is rarely used, and there are plently of alternatives. This preserves the iloc API to be purely positional
based.
In [10]: df = DataFrame(lrange(5), list('ABCDE'), columns=['a'])
In [11]: mask = (df.a%2 == 0)
In [12]: mask
Out[12]:
A
True
B
False
C
True
D
False
E
True
Name: a, dtype: bool
# this is what you should use
In [13]: df.loc[mask]
Out[13]:
a
A 0
C 2
E 4
[3 rows x 1 columns]
161
With
import pandas as pd
pd.read_excel('path_to_file.xls', 'Sheet1', index_col=None, na_values=['NA'])
DataFrame.to_html and DataFrame.to_latex now accept a path for their first argument (GH3702)
Do not allow astypes on datetime64[ns] except to object, and timedelta64[ns] to object/int
(GH3425)
The behavior of datetime64 dtypes has changed with respect to certain so-called reduction operations
(GH3726). The following operations now raise a TypeError when perfomed on a Series and return an
empty Series when performed on a DataFrame similar to performing these operations on, for example, a
DataFrame of slice objects:
sum, prod, mean, std, var, skew, kurt, corr, and cov
162
read_html now defaults to None when reading, and falls back on bs4 + html5lib when lxml fails to
parse. a list of parsers to try until success is also valid
The internal pandas class hierarchy has changed (slightly). The previous PandasObject now is called
PandasContainer and a new PandasObject has become the baseclass for PandasContainer as well
as Index, Categorical, GroupBy, SparseList, and SparseArray (+ their base classes). Currently,
PandasObject provides string methods (from StringMixin). (GH4090, GH4092)
New StringMixin that, given a __unicode__ method, gets python 2 and python 3 compatible string
methods (__str__, __bytes__, and __repr__). Plus string safety throughout. Now employed in many
places throughout the pandas library. (GH4090, GH4092)
print(df == alist[0])
b
True
True
True
[3 rows x 2 columns]
Note that alist here is a Python list so pd.read_html() and DataFrame.to_html() are not inverses.
pd.read_html() no longer performs hard conversion of date strings (GH3656).
Warning: You may have to install an older version of BeautifulSoup4, See the installation docs
Added module for reading and writing Stata files: pandas.io.stata (GH1512) accessable via
read_stata top-level function for reading, and to_stata DataFrame method for writing, See the docs
Added module for reading and writing json format files: pandas.io.json accessable via read_json toplevel function for reading, and to_json DataFrame method for writing, See the docs various issues (GH1226,
GH3804, GH3876, GH3867, GH1305)
MultiIndex column support for reading and writing csv format files
163
The header option in read_csv now accepts a list of the rows from which to read the index.
The option, tupleize_cols can now be specified in both to_csv and read_csv, to provide compatiblity for the pre 0.12 behavior of writing and reading MultIndex columns via a list of tuples. The
default in 0.12 is to write lists of tuples and not interpret list of tuples as a MultiIndex column.
Note: The default behavior in 0.12 remains unchanged from prior versions, but starting with 0.13, the
default to write and read MultiIndex columns will be in the new format. (GH3571, GH1651, GH3141)
If an index_col is not specified (e.g. you dont have an index, or wrote it with df.to_csv(...,
index=False), then any names on the columns index will be lost.
In [20]: from pandas.util.testing import makeCustomDataframe as mkdf
In [21]: df = mkdf(5,3,r_idx_nlevels=2,c_idx_nlevels=4)
In [22]: df.to_csv('mi.csv',tupleize_cols=False)
In [23]: print(open('mi.csv').read())
C0,,C_l0_g0,C_l0_g1,C_l0_g2
C1,,C_l1_g0,C_l1_g1,C_l1_g2
C2,,C_l2_g0,C_l2_g1,C_l2_g2
C3,,C_l3_g0,C_l3_g1,C_l3_g2
R0,R1,,,
R_l0_g0,R_l1_g0,R0C0,R0C1,R0C2
R_l0_g1,R_l1_g1,R1C0,R1C1,R1C2
R_l0_g2,R_l1_g2,R2C0,R2C1,R2C2
R_l0_g3,R_l1_g3,R3C0,R3C1,R3C2
R_l0_g4,R_l1_g4,R4C0,R4C1,R4C2
In [24]: pd.read_csv('mi.csv',header=[0,1,2,3],index_col=[0,1],tupleize_cols=False)
Out[24]:
C0
C_l0_g0 C_l0_g1 C_l0_g2
C1
C_l1_g0 C_l1_g1 C_l1_g2
C2
C_l2_g0 C_l2_g1 C_l2_g2
C3
C_l3_g0 C_l3_g1 C_l3_g2
R0
R1
R_l0_g0 R_l1_g0
R0C0
R0C1
R0C2
R_l0_g1 R_l1_g1
R1C0
R1C1
R1C2
R_l0_g2 R_l1_g2
R2C0
R2C1
R2C2
R_l0_g3 R_l1_g3
R3C0
R3C1
R3C2
R_l0_g4 R_l1_g4
R4C0
R4C1
R4C2
[5 rows x 3 columns]
164
1 -0.661062
2 0.344342
0
3 -0.626968
4 -0.930687
5 0.949965
0
6 -0.402985
7 -0.241527
8 0.049355
0
9 -1.502767
0.862877
0.149565
1
-0.875772
-0.218983
-0.442354
1
1.111358
-0.670477
0.632633
1
-1.225492
read_csv will now throw a more informative error message when a file contains no columns, e.g., all newline
characters
to replace all occurrences of the string . with zero or more instances of surrounding whitespace with NaN.
Regular string replacement still works as expected. For example, you can do
In [27]: df.replace('.', np.nan)
Out[27]:
a b
0
a 1
1
b 2
2 NaN 3
3 NaN 4
[4 rows x 2 columns]
165
In [28]: pd.get_option('a.b')
Out[28]: 2
In [29]: pd.get_option('b.c')
Out[29]: 3
In [30]: pd.set_option('a.b', 1, 'b.c', 4)
In [31]: pd.get_option('a.b')
Out[31]: 1
In [32]: pd.get_option('b.c')
Out[32]: 4
The filter method for group objects returns a subset of the original object. Suppose we want to take only
elements that belong to groups with a group sum greater than 2.
In [33]: sf = Series([1, 1, 2, 3, 3, 3])
In [34]: sf.groupby(sf).filter(lambda x: x.sum() > 2)
Out[34]:
3
3
4
3
5
3
dtype: int64
The argument of filter must a function that, applied to the group as a whole, returns True or False.
Another useful operation is filtering out elements that belong to groups with only a couple members.
In [35]: dff = DataFrame({'A': np.arange(8), 'B': list('aabbbbcc')})
In [36]: dff.groupby('B').filter(lambda x: len(x) > 2)
Out[36]:
A B
2 2 b
3 3 b
4 4 b
5 5 b
[4 rows x 2 columns]
Alternatively, instead of dropping the offending groups, we can return a like-indexed objects where the groups
that do not pass the filter are filled with NaNs.
In [37]: dff.groupby('B').filter(lambda x: len(x) > 2, dropna=False)
Out[37]:
A
B
0 NaN NaN
1 NaN NaN
2
2
b
3
3
b
4
4
b
5
5
b
6 NaN NaN
7 NaN NaN
[8 rows x 2 columns]
Series and DataFrame hist methods now take a figsize argument (GH3834)
166
DatetimeIndexes no longer try to convert mixed-integer indexes during join operations (GH3877)
Timestamp.min and Timestamp.max now represent valid Timestamp instances instead of the default datetime.min and datetime.max (respectively), thanks @SleepingPills
read_html now raises when no tables are found and BeautifulSoup==4.2.0 is detected (GH4214)
167
The last element yielded by the iterator will be a Series containing the last element of the longest string in
the Series with all other elements being NaN. Here since slow is the longest string and there are no other
strings with the same length w is the only non-null string in the yielded Series.
HDFStore
will retain index attributes (freq,tz,name) on recreation (GH3499)
will warn with a AttributeConflictWarning if you are attempting to append an index with a
different frequency than the existing, or attempting to append an index with a different name than the
existing
support datelike columns with a timezone as data_columns (GH2852)
Non-unique index support clarified (GH3468).
Fix assigning a new index to a duplicate index in a DataFrame would fail (GH3468)
Fix construction of a DataFrame with a duplicate index
ref_locs support to allow duplicative indices across dtypes, allows iget support to always find the index
(even across dtypes) (GH2194)
168
applymap on a DataFrame with a non-unique index now works (removed warning) (GH2786), and fix
(GH3230)
Fix to_csv to handle non-unique columns (GH3495)
Duplicate indexes with getitem will return items in the correct order (GH3455, GH3457) and handle missing elements like unique indices (GH3561)
Duplicate indexes with and empty DataFrame.from_records will return a correct frame (GH3562)
Concat to produce a non-unique columns when duplicates are across dtypes is fixed (GH3602)
Allow insert/delete to non-unique columns (GH3679)
Non-unique indexing with a slice via loc and friends fixed (GH3659)
Allow insert/delete to non-unique columns (GH3679)
Extend reindex to correctly deal with non-unique indices (GH3679)
DataFrame.itertuples() now works with frames with duplicate column names (GH3873)
Bug in non-unique indexing via iloc (GH4017); added takeable argument to reindex for locationbased taking
Allow non-unique indexing in series via .ix/.loc and __getitem__ (GH4246)
Fixed non-unique indexing memory allocation issue with .ix/.loc (GH4280)
DataFrame.from_records did not accept empty recarrays (GH3682)
read_html now correctly skips tests (GH3741)
Fixed a bug where DataFrame.replace with a compiled regular expression in the to_replace argument
wasnt working (GH3907)
Improved network test decorator to catch IOError (and therefore URLError as well). Added
with_connectivity_check decorator to allow explicitly checking a website as a proxy for seeing if there
is network connectivity. Plus, new optional_args decorator factory for decorators. (GH3910, GH3914)
Fixed testing issue where too many sockets where open thus leading to a connection reset issue (GH3982,
GH3985, GH4028, GH4054)
Fixed failing tests in test_yahoo, test_google where symbols were not retrieved but were being accessed
(GH3982, GH3985, GH4028, GH4054)
Series.hist will now take the figure from the current environment if one is not passed
Fixed bug where a 1xN DataFrame would barf on a 1xN mask (GH4071)
Fixed running of tox under python3 where the pickle import was getting rewritten in an incompatible way
(GH4062, GH4063)
Fixed bug where sharex and sharey were not being passed to grouped_hist (GH4089)
Fixed bug in DataFrame.replace where a nested dict wasnt being iterated over when regex=False
(GH4115)
Fixed bug in the parsing of microseconds when using the format argument in to_datetime (GH4152)
Fixed bug in PandasAutoDateLocator
MilliSecondLocator (GH3990)
where
invert_xaxis
triggered
incorrectly
Fixed bug in plotting that wasnt raising on invalid colormap for matplotlib 1.1.1 (GH4215)
Fixed the legend displaying in DataFrame.plot(kind=kde) (GH4216)
Fixed bug where Index slices werent carrying the name attribute (GH4226)
169
Fixed bug in initializing DatetimeIndex with an array of strings in a certain time zone (GH4229)
Fixed bug where html5lib wasnt being properly skipped (GH4265)
Fixed bug where get_data_famafrench wasnt using the correct file edges (GH4281)
See the full release notes or issue tracker on GitHub for a complete list.
1.13.3 Dtypes
Numeric dtypes will propagate and can coexist in DataFrames. If a dtype is passed (either directly via the dtype
keyword, a passed ndarray, or a passed Series, then it will be preserved in DataFrame operations. Furthermore,
different numeric dtypes will NOT be combined. The following example will give you a taste.
In [1]: df1 = DataFrame(randn(8, 1), columns = ['A'], dtype = 'float32')
In [2]: df1
Out[2]:
A
0 1.392665
1 -0.123497
2 -0.402761
3 -0.246604
4 -0.288433
5 -0.763434
6 2.069526
7 -1.203569
[8 rows x 1 columns]
In [3]: df1.dtypes
Out[3]:
A
float32
dtype: object
In [4]: df2 = DataFrame(dict( A = Series(randn(8),dtype='float16'),
...:
B = Series(randn(8)),
...:
C = Series(randn(8),dtype='uint8') ))
...:
In [5]: df2
Out[5]:
A
B
0 0.591797 -0.038605
1 0.841309 -0.460478
2 -0.500977 -0.310458
3 -0.816406 0.866493
4 -0.207031 0.245972
5 -0.664062 0.319442
6 0.580566 1.378512
7 -0.965820 0.292502
C
0
1
0
254
0
1
1
255
[8 rows x 3 columns]
In [6]: df2.dtypes
171
Out[6]:
A
float16
B
float64
C
uint8
dtype: object
# here you get some upcasting
In [7]: df3 = df1.reindex_like(df2).fillna(value=0.0) + df2
In [8]: df3
Out[8]:
A
B
0 1.984462 -0.038605
1 0.717812 -0.460478
2 -0.903737 -0.310458
3 -1.063011 0.866493
4 -0.495465 0.245972
5 -1.427497 0.319442
6 2.650092 1.378512
7 -2.169390 0.292502
C
0
1
0
254
0
1
1
255
[8 rows x 3 columns]
In [9]: df3.dtypes
Out[9]:
A
float32
B
float64
C
float64
dtype: object
Conversion
In [11]: df3.astype('float32').dtypes
Out[11]:
A
float32
B
float32
C
float32
dtype: object
Mixed Conversion
In [12]: df3['D'] = '1.'
In [13]: df3['E'] = '1'
In [14]: df3.convert_objects(convert_numeric=True).dtypes
Out[14]:
A
float32
B
float64
C
float64
172
D
float64
E
int64
dtype: object
# same, but specific dtype conversion
In [15]: df3['D'] = df3['D'].astype('float16')
In [16]: df3['E'] = df3['E'].astype('int32')
In [17]: df3.dtypes
Out[17]:
A
float32
B
float64
C
float64
D
float16
E
int32
dtype: object
173
a
int64
dtype: object
D
1
1
1
1
1
1
1
1
E
1
1
1
1
1
1
1
1
[8 rows x 5 columns]
In [27]: dfi.dtypes
Out[27]:
A
int32
B
int32
C
int32
D
int64
E
int32
dtype: object
In [28]: casted = dfi[dfi>0]
In [29]: casted
Out[29]:
A
B
C
0
1 NaN NaN
1 NaN NaN
1
2 NaN NaN NaN
3 NaN NaN 254
4 NaN NaN NaN
5 NaN NaN
1
6
2
1
1
7 NaN NaN 255
D
1
1
1
1
1
1
1
1
E
1
1
1
1
1
1
1
1
[8 rows x 5 columns]
In [30]: casted.dtypes
Out[30]:
A
float64
B
float64
C
float64
D
int64
174
E
int32
dtype: object
C
NaN
1
NaN
254
NaN
1
1
255
D
1
1
1
1
1
1
1
1
E
1
1
1
1
1
1
1
1
[8 rows x 5 columns]
In [36]: casted.dtypes
Out[36]:
A
float32
B
float64
C
float64
D
float16
E
int32
dtype: object
timestamp
175
2001-01-02
2001-01-03
2001-01-04
2001-01-05
2001-01-06
2001-01-07
1.023958
1.236475
-0.270630
-0.440747
-0.632102
-1.444787
0.660103
-2.170629
-1.685677
-0.115070
-0.585977
-0.201135
2001-01-03
2001-01-03
2001-01-03
2001-01-03
2001-01-03
2001-01-03
[6 rows x 3 columns]
# datetime64[ns] out of the box
In [40]: df.get_dtype_counts()
Out[40]:
datetime64[ns]
1
float64
2
dtype: int64
# use the traditional nan, which is mapped to NaT internally
In [41]: df.ix[2:4,['A','timestamp']] = np.nan
In [42]: df
Out[42]:
A
B
2001-01-02 1.023958 0.660103
2001-01-03 1.236475 -2.170629
2001-01-04
NaN -1.685677
2001-01-05
NaN -0.115070
2001-01-06 -0.632102 -0.585977
2001-01-07 -1.444787 -0.201135
timestamp
2001-01-03
2001-01-03
NaT
NaT
2001-01-03
2001-01-03
[6 rows x 3 columns]
176
2
2001-01-02 00:00:00
dtype: object
In [51]: s.dtype
Out[51]: dtype('O')
1.13.8 Enhancements
Improved performance of df.to_csv() by up to 10x in some cases. (GH3059)
Numexpr is now a Recommended Dependencies, to accelerate certain types of numerical and boolean operations
Bottleneck is now a Recommended Dependencies, to accelerate certain types of nan operations
HDFStore
support read_hdf/to_hdf API similar to read_csv/to_csv
In [52]: df = DataFrame(dict(A=lrange(5), B=lrange(5)))
In [53]: df.to_hdf('store.h5','table',append=True)
In [54]: read_hdf('store.h5', 'table', where = ['index>2'])
Out[54]:
A B
3 3 3
4 4 4
[2 rows x 2 columns]
provide dotted attribute access to get from stores, e.g. store.df == store[df]
new keywords iterator=boolean, and chunksize=number_in_a_chunk are provided to support iteration on select and select_as_multiple (GH3076)
You can now select timestamps from an unordered timeseries similarly to an ordered timeseries (GH2437)
You can now select with a string from a DataFrame with a datelike index, in a similar way to a Series (GH3070)
In [55]: idx = date_range("2001-10-1", periods=5, freq='M')
In [56]: ts = Series(np.random.rand(len(idx)),index=idx)
In [57]: ts['2001']
Out[57]:
2001-10-31
0.663256
2001-11-30
0.079126
2001-12-31
0.587699
177
In pd.io.data.Options,
Fix bug when trying to fetch data for the current month when already past expiry.
Now using lxml to scrape html instead of BeautifulSoup (lxml was faster).
New instance variables for calls and puts are automatically created when a method that creates them is
called. This works for current month where the instance variables are simply calls and puts. Also
works for future expiry months and save the instance variable as callsMMYY or putsMMYY, where
MMYY are, respectively, the month and year of the options expiry.
Options.get_near_stock_price now allows the user to specify the month for which to get relevant options data.
178
Options.get_forward_data now has optional kwargs near and above_below. This allows the
user to specify if they would like to only return forward looking data for options near the current stock
price. This just obtains the data from Options.get_near_stock_price instead of Options.get_xxx_data()
(GH2758).
Cursor coordinate information is now displayed in time-series plots.
added option display.max_seq_items to control the number of elements printed per sequence pprinting it.
(GH2979)
added option display.chop_threshold to control display of small numerical values. (GH2739)
added option display.max_info_rows to prevent verbose_info from being calculated for frames above 1M rows
(configurable). (GH2807, GH2918)
value_counts() now accepts a normalize argument, for normalized histograms. (GH2710).
DataFrame.from_records now accepts not only dicts but any instance of the collections.Mapping ABC.
added option display.mpl_style providing a
https://gist.github.com/huyng/816622 (GH3075).
sleeker
visual
style
for
plots.
Based
on
Treat boolean values as integers (values 1 and 0) for numeric operations. (GH2641)
to_html() now accepts an optional escape argument to control reserved HTML character escaping (enabled
by default) and escapes &, in addition to < and >. (GH2919)
See the full release notes or issue tracker on GitHub for a complete list.
179
1.14.3 HDFStore
You may need to upgrade your existing data files. Please visit the compatibility section in the main docs.
You can designate (and index) certain columns that you want to be able to perform queries on a table, by passing a list
to data_columns
In [1]: store = HDFStore('store.h5')
In [2]: df = DataFrame(randn(8, 3), index=date_range('1/1/2000', periods=8),
...:
columns=['A', 'B', 'C'])
...:
In [3]: df['string'] = 'foo'
In [4]: df.ix[4:6,'string'] = np.nan
In [5]: df.ix[7:9,'string'] = 'bar'
In [6]: df['string2'] = 'cool'
In [7]: df
Out[7]:
2000-01-01
2000-01-02
2000-01-03
2000-01-04
2000-01-05
2000-01-06
2000-01-07
2000-01-08
A
1.885136
0.180759
-0.294467
3.127110
-0.242846
0.820521
-0.034086
-2.290958
B
C string string2
-0.183873 2.550850
foo
cool
-1.117089 0.061462
foo
cool
-0.591411 -0.876691
foo
cool
1.451130 0.045152
foo
cool
1.195819 1.533294
NaN
cool
-0.281201 1.651561
NaN
cool
0.252394 -0.498772
foo
cool
-1.601262 -0.256718
bar
cool
[8 rows x 5 columns]
# on-disk operations
In [8]: store.append('df', df, data_columns = ['B','C','string','string2'])
In [9]: store.select('df',[ 'B > 0', 'string == foo' ])
Out[9]:
Empty DataFrame
Columns: [A, B, C, string, string2]
Index: []
[0 rows x 5 columns]
# this is in-memory version of this type of selection
In [10]: df[(df.B > 0) & (df.string == 'foo')]
Out[10]:
A
B
C string string2
2000-01-04 3.127110 1.451130 0.045152
foo
cool
2000-01-07 -0.034086 0.252394 -0.498772
foo
cool
[2 rows x 5 columns]
180
store.unique('df','index')
store.unique('df','string')
= df.copy()
A
1.885136
0.180759
-0.294467
NaN
-0.242846
0.820521
-0.034086
-2.290958
B
C string string2 datetime64
-0.183873 2.550850
foo
cool 2001-01-02
-1.117089 0.061462
foo
cool 2001-01-02
-0.591411 -0.876691
foo
cool 2001-01-02
NaN 0.045152
foo
cool 2001-01-02
1.195819 1.533294
NaN
cool 2001-01-02
-0.281201 1.651561
NaN
cool 2001-01-02
0.252394 -0.498772
foo
cool 2001-01-02
-1.601262 -0.256718
bar
cool 2001-01-02
[8 rows x 6 columns]
In [17]: df_mixed1.get_dtype_counts()
Out[17]:
datetime64[ns]
1
float64
3
object
2
dtype: int64
You can pass columns keyword to select to filter a list of the return columns, this is equivalent to passing a
Term(columns,list_of_columns_to_filter)
In [18]: store.select('df',columns = ['A','B'])
Out[18]:
A
B
2000-01-01 1.885136 -0.183873
2000-01-02 0.180759 -1.117089
2000-01-03 -0.294467 -0.591411
2000-01-04 3.127110 1.451130
2000-01-05 -0.242846 1.195819
2000-01-06 0.820521 -0.281201
2000-01-07 -0.034086 0.252394
2000-01-08 -2.290958 -1.601262
[8 rows x 2 columns]
181
names=['foo', 'bar'])
....:
....:
0.239369
-1.948006
-0.361633
0.152288
-0.859278
-0.647604
-0.342928
0.104020
-0.019240
-0.637855
0.174122
0.980347
-0.761218
-0.862613
1.498195
1.511487
-0.007364
2.052171
-1.713238
0.215109
-1.131794
-0.674429
1.768215
-0.210968
0.462413
-0.727189
1.427674
-1.230963
0.838912
-1.515362
C
-1.131794
-0.674429
1.768215
-0.210968
0.462413
-0.727189
1.427674
-1.230963
0.838912
-1.515362
Multi-table creation via append_to_multiple and selection via select_as_multiple can create/select from
multiple tables and return a combined result, by using where on a selector table.
In [25]: df_mt = DataFrame(randn(8, 6), index=date_range('1/1/2000', periods=8),
....:
columns=['A', 'B', 'C', 'D', 'E', 'F'])
....:
182
In [28]: store
Out[28]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df
frame_table (typ->appendable,nrows->8,ncols->5,indexers->[index],dc->[B,C,strin
/df1_mt
frame_table (typ->appendable,nrows->8,ncols->2,indexers->[index],dc->[A,B])
/df2_mt
frame_table (typ->appendable,nrows->8,ncols->5,indexers->[index])
/df_mixed
frame_table (typ->appendable,nrows->8,ncols->6,indexers->[index])
/mi
frame_table (typ->appendable_multi,nrows->10,ncols->5,indexers->[index],dc->[ba
# indiviual tables were created
In [29]: store.select('df1_mt')
Out[29]:
A
B
2000-01-01 1.586924 -0.447974
2000-01-02 -0.102206 0.870302
2000-01-03 1.249874 1.458210
2000-01-04 -0.616293 0.150468
2000-01-05 -0.431163 0.016640
2000-01-06 0.800353 -0.451572
2000-01-07 1.239198 0.185437
2000-01-08 -0.040863 0.290110
[8 rows x 2 columns]
In [30]: store.select('df2_mt')
Out[30]:
C
D
E
F
2000-01-01 -1.573998 0.630925 -0.071659 -1.277640
2000-01-02 1.275280 -1.199212 1.060780 1.673018
2000-01-03 -0.710542 0.825392 1.557329 1.993441
2000-01-04 0.132104 0.580923 -0.128750 1.445964
2000-01-05 0.904578 -1.645852 -0.688741 0.228006
2000-01-06 0.831767 0.228760 0.932498 -2.200069
2000-01-07 -0.540770 -0.370038 1.298390 1.662964
2000-01-08 -0.096145 1.717830 -0.462446 -0.112019
foo
bar
bar
bar
bar
bar
bar
bar
bar
[8 rows x 5 columns]
# as a multiple
In [31]: store.select_as_multiple(['df1_mt','df2_mt'], where = [ 'A>0','B>0' ], selector = 'df1_mt')
Out[31]:
A
B
C
D
E
F foo
2000-01-03 1.249874 1.458210 -0.710542 0.825392 1.557329 1.993441 bar
2000-01-07 1.239198 0.185437 -0.540770 -0.370038 1.298390 1.662964 bar
[2 rows x 7 columns]
Enhancements
HDFStore now can read native PyTables table format tables
You can pass nan_rep = my_nan_rep to append, to change the default nan representation on disk
(which converts to/from np.nan), this defaults to nan.
1.14. v0.10.1 (January 22, 2013)
183
You can pass index to append. This defaults to True. This will automagically create indicies on the
indexables and data columns of the table
You can pass chunksize=an integer to append, to change the writing chunksize (default is 50000).
This will signficantly lower your memory usage on writing.
You can pass expectedrows=an integer to the first append, to set the TOTAL number of expectedrows
that PyTables will expected. This will optimize read/write performance.
Select now supports passing start and stop to provide selection space limiting in selection.
Greatly improved ISO8601 (e.g., yyyy-mm-dd) date parsing for file parsers (GH2698)
Allow DataFrame.merge to handle combinatorial sizes too large for 64-bit integer (GH2690)
Series now has unary negation (-series) and inversion (~series) operators (GH2686)
DataFrame.plot now includes a logx parameter to change the x-axis to log scale (GH2327)
Series arithmetic operators can now handle constant and ndarray input (GH2574)
ExcelFile now takes a kind argument to specify the file type (GH2613)
A faster implementation for Series.str methods (GH2602)
Bug Fixes
HDFStore tables can now store float32 types correctly (cannot be mixed with float64 however)
Fixed Google Analytics prefix when specifying request segment (GH2713).
Function to reset Google Analytics token store so users can recover from improperly setup client secrets
(GH2687).
Fixed groupby bug resulting in segfault when passing in MultiIndex (GH2706)
Fixed bug where passing a Series with datetime64 values into to_datetime results in bogus output values
(GH2699)
Fixed bug in pattern in HDFStore expressions when pattern is not a valid regex (GH2694)
Fixed performance issues while aggregating boolean data (GH2692)
When given a boolean mask key and a Series of new values, Series __setitem__ will now align the incoming
values with the original Series (GH2686)
Fixed MemoryError caused by performing counting sort on sorting MultiIndex levels with a very large number
of combinatorial values (GH2684)
Fixed bug that causes plotting to fail when the index is a DatetimeIndex with a fixed-offset timezone (GH2683)
Corrected businessday subtraction logic when the offset is more than 5 bdays and the starting date is on a
weekend (GH2680)
Fixed C file parser behavior when the file has more columns than data (GH2668)
Fixed file reader bug that misaligned columns with data in the presence of an implicit column and a specified
usecols value
DataFrames with numerical or datetime indices are now sorted prior to plotting (GH2609)
Fixed DataFrame.from_records error when passed columns, index, but empty records (GH2633)
Several bug fixed for Series operations when dtype is datetime64 (GH2689, GH2629, GH2626)
See the full release notes or issue tracker on GitHub for a complete list.
184
0
-0.134024
-1.626124
-1.565401
-0.302741
0.268766
-0.639757
1
2
3
-0.205969 1.348944 -1.198246
0.982041 0.059493 -0.460111
-0.025706 0.942864 2.502156
0.261551 -0.066342 0.897097
-1.225092 0.582752 -1.490764
-0.952750 -0.892402 0.505987
[6 rows x 4 columns]
185
# deprecated now
In [4]: df - df[0]
Out[4]:
2000-01-01 00:00:00
2000-01-01
NaN
2000-01-02
NaN
2000-01-03
NaN
2000-01-04
NaN
2000-01-05
NaN
2000-01-06
NaN
2000-01-02 00:00:00
NaN
NaN
NaN
NaN
NaN
NaN
2000-01-03 00:00:00
NaN
NaN
NaN
NaN
NaN
NaN
2000-01-04 00:00:00
NaN
NaN
NaN
NaN
NaN
NaN
2000-01-05 00:00:00
NaN
NaN
NaN
NaN
NaN
NaN
2000-01-06 00:00:00
NaN
NaN
NaN
NaN
NaN
NaN
0
NaN
NaN
NaN
NaN
NaN
NaN
2000-01-01
2000-01-02
2000-01-03
2000-01-04
2000-01-05
2000-01-06
2000-01-01
2000-01-02
2000-01-03
2000-01-04
2000-01-05
2000-01-06
1
NaN
NaN
NaN
NaN
NaN
NaN
2
NaN
NaN
NaN
NaN
NaN
NaN
3
NaN
NaN
NaN
NaN
NaN
NaN
[6 rows x 10 columns]
# Change your code to
In [5]: df.sub(df[0], axis=0) # align on axis 0 (rows)
Out[5]:
0
1
2
3
2000-01-01 0 -0.071946 1.482967 -1.064223
2000-01-02 0 2.608165 1.685618 1.166013
2000-01-03 0 1.539695 2.508265 4.067556
2000-01-04 0 0.564293 0.236399 1.199839
2000-01-05 0 -1.493857 0.313986 -1.759530
2000-01-06 0 -0.312993 -0.252645 1.145744
[6 rows x 4 columns]
You will get a deprecation warning in the 0.10.x series, and the deprecated functionality will be removed in 0.11 or
later.
Altered resample default behavior
The default time series resample binning behavior of daily D and higher frequencies has been changed to
closed=left, label=left. Lower nfrequencies are unaffected. The prior defaults were causing a great
deal of confusion for users, especially resampling data to daily frequency (which labeled the aggregated group with
the end of the interval: the next day).
Note:
In [6]: dates = pd.date_range('1/1/2000', '1/5/2000', freq='4h')
In [7]: series = Series(np.arange(len(dates)), index=dates)
In [8]: series
186
Out[8]:
2000-01-01
2000-01-01
2000-01-01
2000-01-01
2000-01-01
2000-01-01
2000-01-02
00:00:00
04:00:00
08:00:00
12:00:00
16:00:00
20:00:00
00:00:00
2000-01-04 00:00:00
2000-01-04 04:00:00
2000-01-04 08:00:00
2000-01-04 12:00:00
2000-01-04 16:00:00
2000-01-04 20:00:00
2000-01-05 00:00:00
Freq: 4H, dtype: int32
0
1
2
3
4
5
6
..
18
19
20
21
22
23
24
Infinity and negative infinity are no longer treated as NA by isnull and notnull. That they every were was
a relic of early pandas. This behavior can be re-enabled globally by the mode.use_inf_as_null option:
In [11]: s = pd.Series([1.5, np.inf, 3.4, -np.inf])
In [12]: pd.isnull(s)
Out[12]:
0
False
1
False
2
False
3
False
dtype: bool
In [13]: s.fillna(0)
Out[13]:
0
1.500000
1
inf
2
3.400000
3
-inf
dtype: float64
187
Methods with the inplace option now all return None instead of the calling object. E.g. code written like
df = df.fillna(0, inplace=True) may stop working. To fix, simply delete the unnecessary variable
assignment.
pandas.merge no longer sorts the group keys (sort=False) by default. This was done for performance
reasons: the group-key sorting is often one of the more expensive parts of the computation and is often unnecessary.
The default column names for a file with no header have been changed to the integers 0 through N - 1. This
is to create consistency with the DataFrame constructor with no columns specified. The v0.9.0 behavior (names
X0, X1, ...) can be reproduced by specifying prefix=X:
In [18]: data= 'a,b,c\n1,Yes,2\n3,No,4'
In [19]: print(data)
a,b,c
1,Yes,2
3,No,4
In [20]: pd.read_csv(StringIO(data), header=None)
Out[20]:
0
1 2
0 a
b c
1 1 Yes 2
2 3
No 4
[3 rows x 3 columns]
In [21]: pd.read_csv(StringIO(data), header=None, prefix='X')
Out[21]:
X0
X1 X2
0 a
b c
1 1 Yes 2
2 3
No 4
[3 rows x 3 columns]
Values like Yes and No are not interpreted as boolean by default, though this can be controlled by new
true_values and false_values arguments:
188
In [22]: print(data)
a,b,c
1,Yes,2
3,No,4
In [23]: pd.read_csv(StringIO(data))
Out[23]:
a
b c
0 1 Yes 2
1 3
No 4
[2 rows x 3 columns]
In [24]: pd.read_csv(StringIO(data), true_values=['Yes'], false_values=['No'])
Out[24]:
a
b c
0 1
True 2
1 3 False 4
[2 rows x 3 columns]
The file parsers will not recognize non-string values arising from a converter function as NA if passed in the
na_values argument. Its better to do post-processing using the replace function instead.
Calling fillna on Series or DataFrame with no arguments is no longer valid code. You must either specify a
fill value or an interpolation method:
In [25]: s = Series([np.nan, 1., 2., np.nan, 4])
In [26]: s
Out[26]:
0
NaN
1
1
2
2
3
NaN
4
4
dtype: float64
In [27]: s.fillna(0)
Out[27]:
0
0
1
1
2
2
3
0
4
4
dtype: float64
In [28]: s.fillna(method='pad')
Out[28]:
0
NaN
1
1
2
2
3
2
4
4
dtype: float64
189
In [29]: s.ffill()
Out[29]:
0
NaN
1
1
2
2
3
2
4
4
dtype: float64
Series.apply will now operate on a returned value from the applied function, that is itself a series, and
possibly upcast the result to a DataFrame
In [30]: def f(x):
....:
return Series([ x, x**2 ], index = ['x', 'x^2'])
....:
In [31]: s = Series(np.random.rand(5))
In [32]: s
Out[32]:
0
0.717478
1
0.815199
2
0.452478
3
0.848385
4
0.235477
dtype: float64
In [33]: s.apply(f)
Out[33]:
x
x^2
0 0.717478 0.514775
1 0.815199 0.664550
2 0.452478 0.204737
3 0.848385 0.719757
4 0.235477 0.055449
[5 rows x 2 columns]
190
0
1
2
3
4
14
15
-0.976847 0.033862
-0.358944 1.262942
-0.276854 0.158399
0.740501 1.510263
-2.069319 -1.115104
[5 rows x 16 columns]
The old behavior of printing out summary information can be achieved via the expand_frame_repr print option:
In [37]: pd.set_option('expand_frame_repr', False)
In [38]: wide_frame
Out[38]:
0
1
2
3
4
5
6
7
8
9
0 -0.681624 0.191356 1.180274 -0.834179 0.703043 0.166568 -0.583599 -1.201796 -1.422811 -0.882554
1 0.441522 -0.316864 -0.017062 1.570114 -0.360875 -0.880096 0.235532 0.207232 -1.983857 -1.702547
2 -0.412451 -0.462580 0.422194 0.288403 -0.487393 -0.777639 0.055865 1.383381 0.085638 0.246392
3 -0.277255 1.331263 0.585174 -0.568825 -0.719412 1.191340 -0.456362 0.089931 0.776079 0.752889
4 -1.642511 0.432560 1.218080 -0.564705 -0.581790 0.286071 0.048725 1.002440 1.276582 0.054399
[5 rows x 16 columns]
The width of each line can be changed via line_width (80 by default):
In [39]: pd.set_option('line_width', 40)
line_width has been deprecated, use display.width instead (currently both are
identical)
In [40]: wide_frame
Out[40]:
0
1
191
0
1
2
3
4
3
4
5
0 -0.834179 0.703043 0.166568
1 1.570114 -0.360875 -0.880096
2 0.288403 -0.487393 -0.777639
3 -0.568825 -0.719412 1.191340
4 -0.564705 -0.581790 0.286071
6
7
8
0 -0.583599 -1.201796 -1.422811
1 0.235532 0.207232 -1.983857
2 0.055865 1.383381 0.085638
3 -0.456362 0.089931 0.776079
4 0.048725 1.002440 1.276582
9
10
11
0 -0.882554 1.209871 -0.941235
1 -1.702547 -1.621234 -0.906840
2 0.246392 0.965887 0.246354
3 0.752889 -1.195795 -1.425911
4 0.054399 0.241963 -0.471786
12
13
0 0.863067 -0.336232
1 1.014601 -0.475108
2 -0.727728 -0.094414
3 -0.548829 0.774225
4 0.314510 -0.059986
14
-0.976847
-0.358944
-0.276854
0.740501
-2.069319
15
0 0.033862
1 1.262942
2 0.158399
3 1.510263
4 -1.115104
[5 rows x 16 columns]
192
C
-0.376280
-0.625256
-0.552429
-0.910942
0.432600
1.844536
-0.955697
0.059904
[8 rows x 3 columns]
In [50]: wp = Panel(randn(2, 5, 4), items=['Item1', 'Item2'],
....:
major_axis=date_range('1/1/2000', periods=5),
....:
minor_axis=['A', 'B', 'C', 'D'])
....:
In [51]: wp
Out[51]:
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 5 (major_axis) x 4 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-01 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to D
# storing a panel
In [52]: store.append('wp',wp)
# selecting via A QUERY
In [53]: store.select('wp',
193
....:
[ Term('major_axis>20000102'), Term('minor_axis', '=', ['A','B']) ])
....:
Out[53]:
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 3 (major_axis) x 2 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-03 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to B
# removing data from tables
In [54]: store.remove('wp', Term('major_axis>20000103'))
Out[54]: 8
In [55]: store.select('wp')
Out[55]:
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 3 (major_axis) x 4 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-01 00:00:00 to 2000-01-03 00:00:00
Minor_axis axis: A to D
# deleting a store
In [56]: del store['df']
In [57]: store
Out[57]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/wp
wide_table
(typ->appendable,nrows->12,ncols->2,indexers->[major_axis,minor_axis])
Enhancements
added ability to hierarchical keys
In [58]: store.put('foo/bar/bah', df)
In [59]: store.append('food/orange', df)
In [60]: store.append('food/apple',
df)
In [61]: store
Out[61]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/foo/bar/bah
frame
(shape->[8,3])
/food/apple
frame_table (typ->appendable,nrows->8,ncols->3,indexers->[index])
/food/orange
frame_table (typ->appendable,nrows->8,ncols->3,indexers->[index])
/wp
wide_table
(typ->appendable,nrows->12,ncols->2,indexers->[major_ax
# remove all nodes under this level
In [62]: store.remove('food')
In [63]: store
Out[63]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/foo/bar/bah
frame
(shape->[8,3])
/wp
wide_table
(typ->appendable,nrows->12,ncols->2,indexers->[major_ax
194
= 1
In [66]: store.append('df',df)
In [67]: df1 = store.select('df')
In [68]: df1
Out[68]:
2000-01-01
2000-01-02
2000-01-03
2000-01-04
2000-01-05
2000-01-06
2000-01-07
2000-01-08
A
-0.369325
0.511936
-0.550627
1.695803
0.426805
0.044671
-2.036047
-0.898872
B
-1.502617
-0.116412
1.261433
-1.025917
-0.131749
-0.341265
0.000830
-0.725411
C
-0.376280
-0.625256
-0.552429
-0.910942
0.432600
1.844536
-0.955697
0.059904
string
string
string
string
string
string
string
string
string
int
1
1
1
1
1
1
1
1
[8 rows x 5 columns]
In [69]: df1.get_dtype_counts()
Out[69]:
float64
3
int64
1
object
1
dtype: int64
195
0.10 of HDFStore is backwards compatible for reading tables created in a prior version of pandas, however, query
terms using the prior (undocumented) methodology are unsupported. You must read in the entire file and write it out
using the new format to take advantage of the updates.
See the full release notes or issue tracker on GitHub for a complete list.
DataFrame.rank now supports additional argument values for the na_option parameter so missing values can
be assigned either the largest or the smallest rank (GH1508, GH2159)
196
DataFrame has new where and mask methods to select values according to a given boolean mask (GH2109,
GH2151)
DataFrame currently supports slicing via a boolean vector the same length as the DataFrame (inside
the []). The returned DataFrame has the same number of columns as the original, but is sliced on its
index.
In [8]: df = DataFrame(np.random.randn(5, 3), columns = ['A','B','C'])
In [9]: df
Out[9]:
0
1
2
3
4
A
B
C
-0.187239 -1.703664 0.613136
-0.948528 0.505346 0.017228
-2.391256 1.207381 0.853174
0.124213 -0.625597 -1.211224
-0.476548 0.649425 0.004610
[5 rows x 3 columns]
197
If a DataFrame is sliced with a DataFrame based boolean condition (with the same size as the original
DataFrame), then a DataFrame the same size (index and columns) as the original is returned, with
elements that do not meet the boolean condition as NaN. This is accomplished via the new method
DataFrame.where. In addition, where takes an optional other argument for replacement.
In [11]: df[df>0]
Out[11]:
A
B
0
NaN
NaN
1
NaN 0.505346
2
NaN 1.207381
3 0.124213
NaN
4
NaN 0.649425
C
0.613136
0.017228
0.853174
NaN
0.004610
[5 rows x 3 columns]
In [12]: df.where(df>0)
Out[12]:
A
B
C
0
NaN
NaN 0.613136
1
NaN 0.505346 0.017228
2
NaN 1.207381 0.853174
3 0.124213
NaN
NaN
4
NaN 0.649425 0.004610
[5 rows x 3 columns]
In [13]: df.where(df>0,-df)
Out[13]:
A
B
C
0 0.187239 1.703664 0.613136
1 0.948528 0.505346 0.017228
2 2.391256 1.207381 0.853174
3 0.124213 0.625597 1.211224
4 0.476548 0.649425 0.004610
[5 rows x 3 columns]
Furthermore, where now aligns the input boolean condition (ndarray or DataFrame), such that partial
selection with setting is possible. This is analagous to partial setting via .ix (but on the contents rather
than the axis labels)
In [14]: df2 = df.copy()
In [15]: df2[ df2[1:4] > 0 ] = 3
In [16]: df2
Out[16]:
A
B
0 -0.187239 -1.703664
1 -0.948528 3.000000
198
C
0.613136
3.000000
Added option to disable pandas-style tick locators and formatters using series.plot(x_compat=True) or pandas.plot_params[x_compat] = True (GH2205)
Existing TimeSeries methods at_time and between_time were added to DataFrame (GH2149)
DataFrame.dot can now accept ndarrays (GH2042)
DataFrame.drop now supports non-unique indexes (GH2101)
Panel.shift now supports negative periods (GH2164)
DataFrame now support unary ~ operator (GH2110)
199
In [22]: s.resample('M')
Out[22]:
2012-01
-0.508759
2012-02
NaN
2012-03
NaN
2012-04
-0.599515
2012-05
NaN
2012-06
NaN
Freq: M, dtype: float64
Period.end_time now returns the last nanosecond in the time interval (GH2124, GH2125, GH1764)
In [23]: p = Period('2012')
In [24]: p.end_time
Out[24]: Timestamp('2012-12-31 23:59:59.999999999')
File parsers no longer coerce to float or bool for columns that have custom converters specified (GH2184)
In [25]: data = 'A,B,C\n00001,001,5\n00002,002,6'
In [26]: read_csv(StringIO(data), converters={'A' : lambda x: x.strip()})
Out[26]:
A B C
0 00001 1 5
1 00002 2 6
[2 rows x 3 columns]
See the full release notes or issue tracker on GitHub for a complete list.
200
Creating a Series from another Series, passing an index, will cause reindexing to happen inside rather than treating the Series like an ndarray. Technically improper usages like Series(df[col1], index=df[col2])
that worked before by accident (this was never intended) will lead to all NA Series in some cases. To be perfectly clear:
In [4]: s1 = Series([1, 2, 3])
In [5]: s1
Out[5]:
0
1
1
2
2
3
dtype: int64
In [6]: s2 = Series(s1, index=['foo', 'bar', 'baz'])
In [7]: s2
Out[7]:
foo
NaN
bar
NaN
baz
NaN
dtype: float64
201
Resolved inconsistencies in specifying custom NA values in text parser. na_values of type dict no longer
override default NAs unless keep_default_na is set to false explicitly (GH1657)
DataFrame.dot will not do data alignment, and also work with Series (GH1915)
See the full release notes or issue tracker on GitHub for a complete list.
202
203
204
../_static/whatsnew_secondary_y.png
Vytautas Jancauskas, the 2012 GSOC participant, has added many new plot types. For example, kde is a new
option:
In [4]: s = Series(np.concatenate((np.random.randn(1000),
...:
np.random.randn(1000) * 0.5 + 3)))
...:
In [5]: plt.figure()
Out[5]: <matplotlib.figure.Figure at 0xaf3dd2ac>
In [6]: s.hist(normed=True, alpha=0.2)
Out[6]: <matplotlib.axes._subplots.AxesSubplot at 0xa862da2c>
In [7]: s.plot(kind='kde')
Out[7]: <matplotlib.axes._subplots.AxesSubplot at 0xa862da2c>
../_static/whatsnew_kde.png
205
pandass Timestamp object is a subclass of datetime.datetime that has nanosecond support (the
nanosecond field store the nanosecond value between 0 and 999). It should substitute directly into any code that
used datetime.datetime values before. Thus, I recommend not casting DatetimeIndex to regular NumPy
arrays.
If you have code that requires an array of datetime.datetime objects, you have a couple of options. First, the
asobject property of DatetimeIndex produces an array of Timestamp objects:
In [15]: stamp_array = rng.asobject
In [16]: stamp_array
Out[16]:
Index([2000-01-01 00:00:00, 2000-01-02 00:00:00, 2000-01-03 00:00:00,
2000-01-04 00:00:00, 2000-01-05 00:00:00, 2000-01-06 00:00:00,
2000-01-07 00:00:00, 2000-01-08 00:00:00, 2000-01-09 00:00:00,
2000-01-10 00:00:00],
dtype='object')
In [17]: stamp_array[5]
Out[17]: Timestamp('2000-01-06 00:00:00', offset='D')
206
array([datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
datetime.datetime(2000,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, 0, 0),
2, 0, 0),
3, 0, 0),
4, 0, 0),
5, 0, 0),
6, 0, 0),
7, 0, 0),
8, 0, 0),
9, 0, 0),
10, 0, 0)], dtype=object)
In [20]: dt_array[5]
Out[20]: datetime.datetime(2000, 1, 6, 0, 0)
matplotlib knows how to handle datetime.datetime but not Timestamp objects. While I recommend that you
plot time series using TimeSeries.plot, you can either use to_pydatetime or register a converter for the
Timestamp type. See matplotlib documentation for more on this.
Warning: There are bugs in the user-facing API with the nanosecond datetime64 unit in NumPy 1.6. In particular,
the string version of the array shows garbage values, and conversion to dtype=object is similarly broken.
In [21]: rng = date_range('1/1/2000', periods=10)
In [22]: rng
Out[22]:
DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04',
'2000-01-05', '2000-01-06', '2000-01-07', '2000-01-08',
'2000-01-09', '2000-01-10'],
dtype='datetime64[ns]', freq='D')
In [23]: np.asarray(rng)
Out[23]:
array(['2000-01-01T01:00:00.000000000+0100',
'2000-01-02T01:00:00.000000000+0100',
'2000-01-03T01:00:00.000000000+0100',
'2000-01-04T01:00:00.000000000+0100',
'2000-01-05T01:00:00.000000000+0100',
'2000-01-06T01:00:00.000000000+0100',
'2000-01-07T01:00:00.000000000+0100',
'2000-01-08T01:00:00.000000000+0100',
'2000-01-09T01:00:00.000000000+0100',
'2000-01-10T01:00:00.000000000+0100'], dtype='datetime64[ns]')
In [24]: converted = np.asarray(rng, dtype=object)
In [25]: converted[5]
Out[25]: 947116800000000000L
Trust me: dont panic. If you are using NumPy 1.6 and restrict your interaction with datetime64 values to
pandass API you will be just fine. There is nothing wrong with the data-type (a 64-bit integer internally); all of the
important data processing happens in pandas and is heavily tested. I strongly recommend that you do not work
directly with datetime64 arrays in NumPy 1.6 and only use the pandas API.
Support for non-unique indexes: In the latter case, you may have code inside a try:... catch: block that
failed due to the index not being unique. In many cases it will no longer fail (some method like append still check for
uniqueness unless disabled). However, all is not lost: you can inspect index.is_unique and raise an exception
explicitly if it is False or go to a different code branch.
207
Add stacked argument to Series and DataFrames plot method for stacked bar plots.
df.plot(kind='bar', stacked=True)
208
df.plot(kind='barh', stacked=True)
209
1
False
2
False
dtype: bool
In [3]: series != 'Steve'
Out[3]:
0
False
1
True
2
True
dtype: bool
In comparisons, NA / NaN will always come through as False except with != which is True. Be very careful with
boolean arithmetic, especially negation, in the presence of NA data. You may wish to add an explicit NA filter into
boolean array operations if you are worried about this:
In [4]: mask = series == 'Steve'
In [5]: series[mask & series.notnull()]
Out[5]:
0
Steve
dtype: object
While propagating NA in comparisons may seem like the right behavior to some users (and you could argue on purely
technical grounds that this is the right thing to do), the evaluation was made that propagating NA everywhere, including
in numerical arrays, would cause a large amount of problems for users. Thus, a practicality beats purity approach
was taken. This issue may be revisited at some point in the future.
C
D
-0.032419 0.237288
-1.581534 0.514679
-0.912061 -1.488101
0.209500 1.018514
-0.675890 -1.488840
0.055228 -1.355434
-1.079181 0.661979
-1.631882 0.708958
[8 rows x 4 columns]
In [8]: grouped = df.groupby('A')['C']
In [9]: grouped.describe()
Out[9]:
210
A
bar
count
mean
std
min
25%
50%
75%
3.000000
-0.438936
0.992521
-1.581534
-0.763153
0.055228
0.132364
...
foo mean
-0.866287
std
0.584196
min
-1.631882
25%
-1.079181
50%
-0.912061
75%
-0.675890
max
-0.032419
dtype: float64
In [10]: grouped.apply(lambda x: x.order()[-2:]) # top 2 values
Out[10]:
A
bar 5
0.055228
3
0.209500
foo 4
-0.675890
0
-0.032419
dtype: float64
211
212
min
25%
50%
75%
max
-1.819334
-0.365166
0.116057
0.616168
1.387310
-1.607906
-0.973095
0.179112
0.807868
1.521442
-1.275249
0.100811
0.718606
0.851809
1.437656
-1.200953
-0.369865
-0.057095
0.237069
1.051356
[8 rows x 4 columns]
213
This is all exactly identical to the behavior before. However, if you ask for a key not contained in the Series, in
versions 0.6.1 and prior, Series would fall back on a location-based lookup. This now raises a KeyError:
In [2]: s[1]
KeyError: 1
1
0.3363
-0.1415
-0.9186
-2.4184
0.3144
-0.7175
-0.3087
0.3410
2
3
-0.1787 0.03162
0.2504 0.58374
-1.4996 0.27163
-0.2658 0.11503
-0.8566 0.61941
-1.0108 0.47990
-0.6049 -0.43544
0.0424 -0.16037
In [5]: df.ix[3]
KeyError: 3
In order to support purely integer-based indexing, the following methods have been added:
214
Method
Series.iget_value(i)
Series.iget(i)
DataFrame.irow(i)
DataFrame.icol(j)
DataFrame.iget_value(i, j)
Description
Retrieve value stored at location i
Alias for iget_value
Retrieve the i-th row
Retrieve the j-th column
Retrieve the value at row i and column j
If the index had been sorted, the range selection would have been possible:
In [11]: s2 = s.sort_index()
In [12]: s2
Out[12]:
a
-0.757308
c
-1.093529
e
-1.921164
g
0.647633
k
-0.759803
m
-0.147670
dtype: float64
In [13]: s2.ix['b':'h']
Out[13]:
c
-1.093529
e
-1.921164
g
0.647633
dtype: float64
215
In the case of integer indexes, the behavior will be exactly as before (shadowing ndarray):
In [19]: s = Series(randn(6), index=range(0, 12, 2))
In [20]: s[[4, 0, 2]]
Out[20]:
4
0.319635
0
0.886170
2
-1.125894
dtype: float64
In [21]: s[1:5]
Out[21]:
2
-1.125894
4
0.319635
6
0.998222
8
0.091743
216
dtype: float64
If you wish to do indexing with sequences and slicing on an integer index with label semantics, use ix.
217
Add Spearman and Kendall rank correlation options to Series.corr and DataFrame.corr (GH428)
Added get_value and set_value methods to Series, DataFrame, and Panel for very low-overhead access
(>2x faster in many cases) to scalar elements (GH437, GH438). set_value is capable of producing an
enlarged object.
Add PyQt table widget to sandbox (GH435)
DataFrame.align can accept Series arguments and an axis option (GH461)
Implement new SparseArray and SparseList data structures. SparseSeries now derives from SparseArray
(GH463)
Better console printing options (GH453)
Implement fast data ranking for Series and DataFrame, fast versions of scipy.stats.rankdata (GH428)
Implement DataFrame.from_items alternate constructor (GH444)
DataFrame.convert_objects method for inferring better dt