Skip to content

Commit 38fa22b

Browse files
committed
ENH: Provide dict object for to_dict() #16122
1 parent 02eafaf commit 38fa22b

File tree

305 files changed

+2980
-1280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

305 files changed

+2980
-1280
lines changed

asv_bench/benchmarks/algorithms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pandas as pd
66
from pandas.util import testing as tm
77

8-
for imp in ['pandas.util.hashing', 'pandas.tools.hashing']:
8+
for imp in ['pandas.util', 'pandas.tools.hashing']:
99
try:
1010
hashing = import_module(imp)
1111
break

asv_bench/benchmarks/attrs_caching.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from .pandas_vb_common import *
2-
from pandas.util.decorators import cache_readonly
2+
3+
try:
4+
from pandas.util import cache_readonly
5+
except ImportError:
6+
from pandas.util.decorators import cache_readonly
37

48

59
class DataFrameAttributes(object):

ci/requirements-3.6_WIN.run

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
python-dateutil
22
pytz
33
numpy=1.12*
4+
bottleneck
45
openpyxl
56
xlsxwriter
67
xlrd

doc/source/api.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,6 @@ strings and apply several methods to it. These can be accessed like
618618
Series.cat
619619
Series.dt
620620
Index.str
621-
CategoricalIndex.str
622621
MultiIndex.str
623622
DatetimeIndex.str
624623
TimedeltaIndex.str
@@ -1404,6 +1403,7 @@ CategoricalIndex
14041403

14051404
.. autosummary::
14061405
:toctree: generated/
1406+
:template: autosummary/class_without_autosummary.rst
14071407

14081408
CategoricalIndex
14091409

@@ -1432,6 +1432,7 @@ IntervalIndex
14321432

14331433
.. autosummary::
14341434
:toctree: generated/
1435+
:template: autosummary/class_without_autosummary.rst
14351436

14361437
IntervalIndex
14371438

doc/source/contributing.rst

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -617,11 +617,11 @@ the expected correct result::
617617
Transitioning to ``pytest``
618618
~~~~~~~~~~~~~~~~~~~~~~~~~~~
619619

620-
*pandas* existing test structure is *mostly* classed based, meaning that you will typically find tests wrapped in a class, inheriting from ``tm.TestCase``.
620+
*pandas* existing test structure is *mostly* classed based, meaning that you will typically find tests wrapped in a class.
621621

622622
.. code-block:: python
623623
624-
class TestReallyCoolFeature(tm.TestCase):
624+
class TestReallyCoolFeature(object):
625625
....
626626
627627
Going forward, we are moving to a more *functional* style using the `pytest <http://doc.pytest.org/en/latest/>`__ framework, which offers a richer testing
@@ -632,14 +632,6 @@ framework that will facilitate testing and developing. Thus, instead of writing
632632
def test_really_cool_feature():
633633
....
634634
635-
Sometimes, it does make sense to bundle test functions together into a single class, either because the test file is testing multiple functions from a single module, and
636-
using test classes allows for better organization. However, instead of inheriting from ``tm.TestCase``, we should just inherit from ``object``:
637-
638-
.. code-block:: python
639-
640-
class TestReallyCoolFeature(object):
641-
....
642-
643635
Using ``pytest``
644636
~~~~~~~~~~~~~~~~
645637

doc/source/merging.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
1414
import matplotlib.pyplot as plt
1515
plt.close('all')
16-
import pandas.util.doctools as doctools
16+
import pandas.util._doctools as doctools
1717
p = doctools.TablePlotter()
1818
1919

doc/source/whatsnew/v0.20.0.txt

Lines changed: 49 additions & 52 deletions
Large diffs are not rendered by default.

doc/source/whatsnew/v0.20.1.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Highlights include:
1818

1919
Enhancements
2020
~~~~~~~~~~~~
21+
- ``Series.to_dict()`` and ``DataFrame.to_dict()`` now support an ``into`` keyword which allows you to specify the ``collections.Mapping`` subclass that you would like returned. The default is ``dict``, which is backwards compatible. (:issue:`16122`)
2122

2223

2324

doc/source/whatsnew/v0.21.0.txt

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
.. _whatsnew_0210:
2+
3+
v0.21.0 (???)
4+
-------------
5+
6+
This is a major release from 0.20.x and includes a number of API changes, deprecations, new features,
7+
enhancements, and performance improvements along with a large number of bug fixes. We recommend that all
8+
users upgrade to this version.
9+
10+
Highlights include:
11+
12+
Check the :ref:`API Changes <whatsnew_0210.api_breaking>` and :ref:`deprecations <whatsnew_0210.deprecations>` before updating.
13+
14+
.. contents:: What's new in v0.21.0
15+
:local:
16+
:backlinks: none
17+
18+
.. _whatsnew_0210.enhancements:
19+
20+
New features
21+
~~~~~~~~~~~~
22+
23+
24+
25+
.. _whatsnew_0210.enhancements.other:
26+
27+
Other Enhancements
28+
^^^^^^^^^^^^^^^^^^
29+
30+
31+
32+
.. _whatsnew_0210.api_breaking:
33+
34+
Backwards incompatible API changes
35+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
36+
37+
38+
39+
.. _whatsnew_0210.api:
40+
41+
Other API Changes
42+
^^^^^^^^^^^^^^^^^
43+
44+
45+
46+
.. _whatsnew_0210.deprecations:
47+
48+
Deprecations
49+
~~~~~~~~~~~~
50+
51+
52+
53+
.. _whatsnew_0210.prior_deprecations:
54+
55+
Removal of prior version deprecations/changes
56+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57+
58+
59+
60+
.. _whatsnew_0210.performance:
61+
62+
Performance Improvements
63+
~~~~~~~~~~~~~~~~~~~~~~~~
64+
65+
66+
67+
.. _whatsnew_0210.bug_fixes:
68+
69+
Bug Fixes
70+
~~~~~~~~~
71+
72+
Conversion
73+
^^^^^^^^^^
74+
75+
76+
77+
Indexing
78+
^^^^^^^^
79+
80+
81+
82+
I/O
83+
^^^
84+
85+
86+
87+
Plotting
88+
^^^^^^^^
89+
90+
91+
92+
Groupby/Resample/Rolling
93+
^^^^^^^^^^^^^^^^^^^^^^^^
94+
95+
96+
97+
Sparse
98+
^^^^^^
99+
100+
101+
102+
Reshaping
103+
^^^^^^^^^
104+
105+
106+
107+
Numeric
108+
^^^^^^^
109+
110+
111+
112+
Other
113+
^^^^^

doc/sphinxext/numpydoc/numpydoc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ def mangle_docstrings(app, what, name, obj, options, lines,
4343
)
4444

4545
# PANDAS HACK (to remove the list of methods/attributes for Categorical)
46-
if what == "class" and name.endswith(".Categorical"):
46+
if what == "class" and (name.endswith(".Categorical") or
47+
name.endswith("CategoricalIndex") or
48+
name.endswith("IntervalIndex")):
4749
cfg['class_members_list'] = False
4850

4951
if what == 'module':

pandas/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,17 @@
5050
import pandas.tools.plotting
5151
plot_params = pandas.plotting._style._Options(deprecated=True)
5252
# do not import deprecate to top namespace
53-
scatter_matrix = pandas.util.decorators.deprecate(
53+
scatter_matrix = pandas.util._decorators.deprecate(
5454
'pandas.scatter_matrix', pandas.plotting.scatter_matrix,
5555
'pandas.plotting.scatter_matrix')
5656

57-
from pandas.util.print_versions import show_versions
57+
from pandas.util._print_versions import show_versions
5858
from pandas.io.api import *
5959
from pandas.util._tester import test
6060
import pandas.testing
6161

6262
# extension module deprecations
63-
from pandas.util.depr_module import _DeprecatedModule
63+
from pandas.util._depr_module import _DeprecatedModule
6464

6565
json = _DeprecatedModule(deprmod='pandas.json',
6666
moved={'dumps': 'pandas.io.json.dumps',
File renamed without changes.
File renamed without changes.
File renamed without changes.

pandas/_libs/src/ujson/python/ujson.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,14 @@ static struct PyModuleDef moduledef = {
9090
NULL /* m_free */
9191
};
9292

93-
#define PYMODINITFUNC PyMODINIT_FUNC PyInit_libjson(void)
93+
#define PYMODINITFUNC PyMODINIT_FUNC PyInit_json(void)
9494
#define PYMODULE_CREATE() PyModule_Create(&moduledef)
9595
#define MODINITERROR return NULL
9696

9797
#else
9898

99-
#define PYMODINITFUNC PyMODINIT_FUNC initlibjson(void)
100-
#define PYMODULE_CREATE() Py_InitModule("libjson", ujsonMethods)
99+
#define PYMODINITFUNC PyMODINIT_FUNC initjson(void)
100+
#define PYMODULE_CREATE() Py_InitModule("json", ujsonMethods)
101101
#define MODINITERROR return
102102

103103
#endif
File renamed without changes.
File renamed without changes.

pandas/compat/numpy/function.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"""
2020

2121
from numpy import ndarray
22-
from pandas.util.validators import (validate_args, validate_kwargs,
23-
validate_args_and_kwargs)
22+
from pandas.util._validators import (validate_args, validate_kwargs,
23+
validate_args_and_kwargs)
2424
from pandas.errors import UnsupportedFunctionCall
2525
from pandas.core.dtypes.common import is_integer, is_bool
2626
from pandas.compat import OrderedDict

pandas/compat/pickle_compat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def load_reduce(self):
7171

7272
# 12588, extensions moving
7373
('pandas._sparse', 'BlockIndex'):
74-
('pandas.core.sparse.libsparse', 'BlockIndex'),
74+
('pandas._libs.sparse', 'BlockIndex'),
7575
('pandas.tslib', 'Timestamp'):
7676
('pandas._libs.tslib', 'Timestamp'),
7777
('pandas.tslib', '__nat_unpickle'):

pandas/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ def pytest_runtest_setup(item):
2525
pytest.skip("skipping due to --skip-network")
2626

2727

28+
# Configurations for all tests and all test modules
29+
30+
@pytest.fixture(autouse=True)
31+
def configure_tests():
32+
pandas.set_option('chained_assignment', 'raise')
33+
34+
2835
# For running doctests: make np and pd names available
2936

3037
@pytest.fixture(autouse=True)

pandas/core/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from pandas.core.resample import TimeGrouper
3636

3737
# see gh-14094.
38-
from pandas.util.depr_module import _DeprecatedModule
38+
from pandas.util._depr_module import _DeprecatedModule
3939

4040
_removals = ['day', 'bday', 'businessDay', 'cday', 'customBusinessDay',
4141
'customBusinessMonthEnd', 'customBusinessMonthBegin',

pandas/core/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
from pandas.core.dtypes.missing import isnull
1010
from pandas.core.dtypes.generic import ABCDataFrame, ABCSeries, ABCIndexClass
1111
from pandas.core.dtypes.common import is_object_dtype, is_list_like, is_scalar
12-
from pandas.util.validators import validate_bool_kwarg
12+
from pandas.util._validators import validate_bool_kwarg
1313

1414
from pandas.core import common as com
1515
import pandas.core.nanops as nanops
1616
import pandas._libs.lib as lib
1717
from pandas.compat.numpy import function as nv
18-
from pandas.util.decorators import (Appender, cache_readonly,
19-
deprecate_kwarg, Substitution)
18+
from pandas.util._decorators import (Appender, cache_readonly,
19+
deprecate_kwarg, Substitution)
2020
from pandas.core.common import AbstractMethodError
2121

2222
_shared_docs = dict()

pandas/core/categorical.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
import pandas.core.common as com
3535
from pandas.core.missing import interpolate_2d
3636
from pandas.compat.numpy import function as nv
37-
from pandas.util.decorators import (Appender, cache_readonly,
38-
deprecate_kwarg, Substitution)
37+
from pandas.util._decorators import (Appender, cache_readonly,
38+
deprecate_kwarg, Substitution)
3939

40-
from pandas.util.terminal import get_terminal_size
41-
from pandas.util.validators import validate_bool_kwarg
40+
from pandas.io.formats.terminal import get_terminal_size
41+
from pandas.util._validators import validate_bool_kwarg
4242
from pandas.core.config import get_option
4343

4444

pandas/core/common.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import warnings
77
from datetime import datetime, timedelta
88
from functools import partial
9+
import inspect
10+
import collections
911

1012
import numpy as np
1113
from pandas._libs import lib, tslib
@@ -479,6 +481,43 @@ def _dict_compat(d):
479481
for key, value in iteritems(d))
480482

481483

484+
def _standardize_mapping(into):
485+
"""
486+
Helper function to standardize the supplied mapping so it can
487+
be passed to the ``Series.to_dict()`` and ``DataFrame.to_dict()``
488+
489+
Parameters
490+
----------
491+
into : instance or subclass of collections.Mapping
492+
The argument supplied to ``to_dict``. Must be a class, an
493+
initialized collections.defaultdict, or an empty instance
494+
of a collections.Mapping subclass.
495+
496+
Returns
497+
-------
498+
mapping : a collections.Mapping subclass or other constructor
499+
a callable object that can accept an iterator to create
500+
the desired Mapping.
501+
502+
"""
503+
if not inspect.isclass(into):
504+
if len(into) > 0:
505+
raise ValueError(
506+
"to_dict() only accepts empty mappings.")
507+
elif type(into) == collections.defaultdict:
508+
return partial(
509+
collections.defaultdict, into.default_factory)
510+
else:
511+
return _standardize_mapping(type(into))
512+
elif not issubclass(into, collections.Mapping):
513+
raise TypeError('unsupported type: {}'.format(into))
514+
elif into == collections.defaultdict:
515+
raise TypeError(
516+
'to_dict() only accepts initialized defaultdicts')
517+
else:
518+
return into
519+
520+
482521
def sentinel_factory():
483522
class Sentinel(object):
484523
pass

0 commit comments

Comments
 (0)