@@ -426,14 +426,14 @@ python/numpy allow slicing past the end of an array without an associated error.
426
426
values. A single indexer that is out-of-bounds and drops the dimensions of the object will still raise
427
427
``IndexError `` (:issue: `6296 `). This could result in an empty axis (e.g. an empty DataFrame being returned)
428
428
429
- .. ipython :: python
429
+ .. ipython :: python
430
430
431
- df = DataFrame(np.random.randn(5 ,2 ),columns = list (' AB' ))
432
- df
433
- df .iloc[[4 ,5 ,6 ]]
434
- df .iloc[4 :6 ]
435
- df .iloc[:,2 :3 ]
436
- df .iloc[:,1 :3 ]
431
+ dfl = DataFrame(np.random.randn(5 ,2 ),columns = list (' AB' ))
432
+ dfl
433
+ dfl .iloc[[4 ,5 ,6 ]]
434
+ dfl .iloc[4 :6 ]
435
+ dfl .iloc[:,2 :3 ]
436
+ dfl .iloc[:,1 :3 ]
437
437
438
438
.. _indexing.basics.partial_setting :
439
439
@@ -1684,47 +1684,143 @@ of tuples:
1684
1684
Advanced indexing with hierarchical index
1685
1685
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1686
1686
1687
- Syntactically integrating ``MultiIndex `` in advanced indexing with ``.ix `` is a
1687
+ Syntactically integrating ``MultiIndex `` in advanced indexing with ``.loc/. ix `` is a
1688
1688
bit challenging, but we've made every effort to do so. for example the
1689
1689
following works as you would expect:
1690
1690
1691
1691
.. ipython :: python
1692
1692
1693
1693
df = df.T
1694
1694
df
1695
- df.ix [' bar' ]
1696
- df.ix [' bar' , ' two' ]
1695
+ df.loc [' bar' ]
1696
+ df.loc [' bar' , ' two' ]
1697
1697
1698
- "Partial" slicing also works quite nicely for the topmost level:
1698
+ "Partial" slicing also works quite nicely.
1699
1699
1700
1700
.. ipython :: python
1701
1701
1702
- df.ix [' baz' :' foo' ]
1702
+ df.loc [' baz' :' foo' ]
1703
1703
1704
- But lower levels cannot be sliced in this way, because the MultiIndex uses
1705
- its multiple index dimensions to slice along one dimension of your object:
1704
+ You can slice with a 'range' of values, by providing a slice of tuples.
1706
1705
1707
1706
.. ipython :: python
1708
1707
1709
- df.ix [(' baz' , ' two' ):(' qux' , ' one' )]
1710
- df.ix [(' baz' , ' two' ):' foo' ]
1708
+ df.loc [(' baz' , ' two' ):(' qux' , ' one' )]
1709
+ df.loc [(' baz' , ' two' ):' foo' ]
1711
1710
1712
1711
Passing a list of labels or tuples works similar to reindexing:
1713
1712
1714
1713
.. ipython :: python
1715
1714
1716
1715
df.ix[[(' bar' , ' two' ), (' qux' , ' one' )]]
1717
1716
1718
- The following does not work, and it's not clear if it should or not :
1717
+ .. _ indexing.mi_slicers :
1719
1718
1720
- ::
1719
+ Multiindexing using slicers
1720
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1721
+
1722
+ .. versionadded :: 0.14.0
1723
+
1724
+ In 0.14.0 we added a new way to slice multi-indexed objects.
1725
+ You can slice a multi-index by providing multiple indexers.
1726
+
1727
+ You can provide any of the selectors as if you are indexing by label, see :ref: `Selection by Label <indexing.label >`,
1728
+ including slices, lists of labels, labels, and boolean indexers.
1729
+
1730
+ You can use ``slice(None) `` to select all the contents of *that * level. You do not need to specify all the
1731
+ *deeper * levels, they will be implied as ``slice(None) ``.
1732
+
1733
+ As usual, **both sides ** of the slicers are included as this is label indexing.
1734
+
1735
+ .. warning ::
1721
1736
1722
- >>> df.ix[['bar', 'qux']]
1737
+ You should specify all axes in the ``.loc `` specifier, meaning the indexer for the **index ** and
1738
+ for the **columns **. Their are some ambiguous cases where the passed indexer could be mis-interpreted
1739
+ as indexing *both * axes, rather than into say the MuliIndex for the rows.
1740
+
1741
+ You should do this:
1742
+
1743
+ .. code-block :: python
1744
+
1745
+ df.loc[(slice (' A1' ,' A3' ),... ..),:]
1746
+
1747
+ rather than this:
1748
+
1749
+ .. code-block :: python
1750
+
1751
+ df.loc[(slice (' A1' ,' A3' ),... ..)]
1752
+
1753
+ .. warning ::
1754
+
1755
+ You will need to make sure that the selection axes are fully lexsorted!
1756
+
1757
+ .. ipython :: python
1758
+
1759
+ def mklbl (prefix ,n ):
1760
+ return [" %s%s " % (prefix,i) for i in range (n)]
1761
+
1762
+ miindex = MultiIndex.from_product([mklbl(' A' ,4 ),
1763
+ mklbl(' B' ,2 ),
1764
+ mklbl(' C' ,4 ),
1765
+ mklbl(' D' ,2 )])
1766
+ micolumns = MultiIndex.from_tuples([(' a' ,' foo' ),(' a' ,' bar' ),
1767
+ (' b' ,' foo' ),(' b' ,' bah' )],
1768
+ names = [' lvl0' , ' lvl1' ])
1769
+ dfmi = DataFrame(np.arange(len (miindex)* len (micolumns)).reshape((len (miindex),len (micolumns))),
1770
+ index = miindex,
1771
+ columns = micolumns).sortlevel().sortlevel(axis = 1 )
1772
+ dfmi
1773
+
1774
+ Basic multi-index slicing using slices, lists, and labels.
1775
+
1776
+ .. ipython :: python
1777
+
1778
+ dfmi.loc[(slice (' A1' ,' A3' ),slice (None ), [' C1' ,' C3' ]),:]
1779
+
1780
+ You can use a ``pd.IndexSlice `` to shortcut the creation of these slices
1781
+
1782
+ .. ipython :: python
1783
+
1784
+ idx = pd.IndexSlice
1785
+ dfmi.loc[idx[:,:,[' C1' ,' C3' ]],idx[:,' foo' ]]
1786
+
1787
+ It is possible to perform quite complicated selections using this method on multiple
1788
+ axes at the same time.
1789
+
1790
+ .. ipython :: python
1723
1791
1724
- The code for implementing ``.ix `` makes every attempt to "do the right thing"
1725
- but as you use it you may uncover corner cases or unintuitive behavior. If you
1726
- do find something like this, do not hesitate to report the issue or ask on the
1727
- mailing list.
1792
+ dfmi.loc[' A1' ,(slice (None ),' foo' )]
1793
+ dfmi.loc[idx[:,:,[' C1' ,' C3' ]],idx[:,' foo' ]]
1794
+
1795
+ Using a boolean indexer you can provide selection related to the *values *.
1796
+
1797
+ .. ipython :: python
1798
+
1799
+ mask = dfmi[(' a' ,' foo' )]> 200
1800
+ dfmi.loc[idx[mask,:,[' C1' ,' C3' ]],idx[:,' foo' ]]
1801
+
1802
+ You can also specify the ``axis `` argument to ``.loc `` to interpret the passed
1803
+ slicers on a single axis.
1804
+
1805
+ .. ipython :: python
1806
+
1807
+ dfmi.loc(axis = 0 )[:,:,[' C1' ,' C3' ]]
1808
+
1809
+ Furthermore you can *set * the values using these methods
1810
+
1811
+ .. ipython :: python
1812
+
1813
+ df2 = dfmi.copy()
1814
+ df2.loc(axis = 0 )[:,:,[' C1' ,' C3' ]] = - 10
1815
+ df2
1816
+
1817
+ You can use a right-hand-side of an alignable object as well.
1818
+
1819
+ .. ipython :: python
1820
+
1821
+ df2 = dfmi.copy()
1822
+ df2.loc[idx[:,:,[' C1' ,' C3' ]],:] = df2* 1000
1823
+ df2
1728
1824
1729
1825
.. _indexing.xs :
1730
1826
@@ -1738,6 +1834,11 @@ selecting data at a particular level of a MultiIndex easier.
1738
1834
1739
1835
df.xs(' one' , level = ' second' )
1740
1836
1837
+ .. ipython :: python
1838
+
1839
+ # using the slicers (new in 0.14.0)
1840
+ df.loc[(slice (None ),' one' ),:]
1841
+
1741
1842
You can also select on the columns with :meth: `~pandas.MultiIndex.xs `, by
1742
1843
providing the axis argument
1743
1844
@@ -1746,29 +1847,38 @@ providing the axis argument
1746
1847
df = df.T
1747
1848
df.xs(' one' , level = ' second' , axis = 1 )
1748
1849
1850
+ .. ipython :: python
1851
+
1852
+ # using the slicers (new in 0.14.0)
1853
+ df.loc[:,(slice (None ),' one' )]
1854
+
1749
1855
:meth: `~pandas.MultiIndex.xs ` also allows selection with multiple keys
1750
1856
1751
1857
.. ipython :: python
1752
1858
1753
1859
df.xs((' one' , ' bar' ), level = (' second' , ' first' ), axis = 1 )
1754
1860
1861
+ .. ipython :: python
1862
+
1863
+ # using the slicers (new in 0.14.0)
1864
+ df.loc[:,(' bar' ,' one' )]
1755
1865
1756
1866
.. versionadded :: 0.13.0
1757
1867
1758
1868
You can pass ``drop_level=False `` to :meth: `~pandas.MultiIndex.xs ` to retain
1759
1869
the level that was selected
1760
1870
1761
- .. ipython ::
1871
+ .. ipython :: python
1762
1872
1763
1873
df.xs(' one' , level = ' second' , axis = 1 , drop_level = False )
1764
1874
1765
1875
versus the result with ``drop_level=True `` (the default value)
1766
1876
1767
- .. ipython ::
1877
+ .. ipython :: python
1768
1878
1769
1879
df.xs(' one' , level = ' second' , axis = 1 , drop_level = True )
1770
1880
1771
- .. ipython ::
1881
+ .. ipython :: python
1772
1882
:suppress:
1773
1883
1774
1884
df = df.T
0 commit comments