data-science-ipython-notebooks/pandas/03.01-Introducing-Pandas-Objects.ipynb
2017-03-13 04:42:29 -04:00

1561 lines
39 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!--BOOK_INFORMATION-->\n",
"<img align=\"left\" style=\"padding-right:10px;\" src=\"figures/PDSH-cover-small.png\">\n",
"*This notebook contains an excerpt from the [Python Data Science Handbook](http://shop.oreilly.com/product/0636920034919.do) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/PythonDataScienceHandbook).*\n",
"\n",
"*The text is released under the [CC-BY-NC-ND license](https://creativecommons.org/licenses/by-nc-nd/3.0/us/legalcode), and code is released under the [MIT license](https://opensource.org/licenses/MIT). If you find this content useful, please consider supporting the work by [buying the book](http://shop.oreilly.com/product/0636920034919.do)!*\n",
"\n",
"*No changes were made to the contents of this notebook from the original.*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!--NAVIGATION-->\n",
"< [Data Manipulation with Pandas](03.00-Introduction-to-Pandas.ipynb) | [Contents](Index.ipynb) | [Data Indexing and Selection](03.02-Data-Indexing-and-Selection.ipynb) >"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introducing Pandas Objects"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At the very basic level, Pandas objects can be thought of as enhanced versions of NumPy structured arrays in which the rows and columns are identified with labels rather than simple integer indices.\n",
"As we will see during the course of this chapter, Pandas provides a host of useful tools, methods, and functionality on top of the basic data structures, but nearly everything that follows will require an understanding of what these structures are.\n",
"Thus, before we go any further, let's introduce these three fundamental Pandas data structures: the ``Series``, ``DataFrame``, and ``Index``.\n",
"\n",
"We will start our code sessions with the standard NumPy and Pandas imports:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Pandas Series Object\n",
"\n",
"A Pandas ``Series`` is a one-dimensional array of indexed data.\n",
"It can be created from a list or array as follows:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0 0.25\n",
"1 0.50\n",
"2 0.75\n",
"3 1.00\n",
"dtype: float64"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = pd.Series([0.25, 0.5, 0.75, 1.0])\n",
"data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we see in the output, the ``Series`` wraps both a sequence of values and a sequence of indices, which we can access with the ``values`` and ``index`` attributes.\n",
"The ``values`` are simply a familiar NumPy array:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0.25, 0.5 , 0.75, 1. ])"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.values"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``index`` is an array-like object of type ``pd.Index``, which we'll discuss in more detail momentarily."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"RangeIndex(start=0, stop=4, step=1)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.index"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Like with a NumPy array, data can be accessed by the associated index via the familiar Python square-bracket notation:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.5"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data[1]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1 0.50\n",
"2 0.75\n",
"dtype: float64"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data[1:3]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we will see, though, the Pandas ``Series`` is much more general and flexible than the one-dimensional NumPy array that it emulates."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ``Series`` as generalized NumPy array"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From what we've seen so far, it may look like the ``Series`` object is basically interchangeable with a one-dimensional NumPy array.\n",
"The essential difference is the presence of the index: while the Numpy Array has an *implicitly defined* integer index used to access the values, the Pandas ``Series`` has an *explicitly defined* index associated with the values.\n",
"\n",
"This explicit index definition gives the ``Series`` object additional capabilities. For example, the index need not be an integer, but can consist of values of any desired type.\n",
"For example, if we wish, we can use strings as an index:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"a 0.25\n",
"b 0.50\n",
"c 0.75\n",
"d 1.00\n",
"dtype: float64"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = pd.Series([0.25, 0.5, 0.75, 1.0],\n",
" index=['a', 'b', 'c', 'd'])\n",
"data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And the item access works as expected:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.5"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data['b']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can even use non-contiguous or non-sequential indices:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2 0.25\n",
"5 0.50\n",
"3 0.75\n",
"7 1.00\n",
"dtype: float64"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = pd.Series([0.25, 0.5, 0.75, 1.0],\n",
" index=[2, 5, 3, 7])\n",
"data"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.5"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data[5]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Series as specialized dictionary\n",
"\n",
"In this way, you can think of a Pandas ``Series`` a bit like a specialization of a Python dictionary.\n",
"A dictionary is a structure that maps arbitrary keys to a set of arbitrary values, and a ``Series`` is a structure which maps typed keys to a set of typed values.\n",
"This typing is important: just as the type-specific compiled code behind a NumPy array makes it more efficient than a Python list for certain operations, the type information of a Pandas ``Series`` makes it much more efficient than Python dictionaries for certain operations.\n",
"\n",
"The ``Series``-as-dictionary analogy can be made even more clear by constructing a ``Series`` object directly from a Python dictionary:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"California 38332521\n",
"Florida 19552860\n",
"Illinois 12882135\n",
"New York 19651127\n",
"Texas 26448193\n",
"dtype: int64"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"population_dict = {'California': 38332521,\n",
" 'Texas': 26448193,\n",
" 'New York': 19651127,\n",
" 'Florida': 19552860,\n",
" 'Illinois': 12882135}\n",
"population = pd.Series(population_dict)\n",
"population"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By default, a ``Series`` will be created where the index is drawn from the sorted keys.\n",
"From here, typical dictionary-style item access can be performed:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"38332521"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"population['California']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Unlike a dictionary, though, the ``Series`` also supports array-style operations such as slicing:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"California 38332521\n",
"Florida 19552860\n",
"Illinois 12882135\n",
"dtype: int64"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"population['California':'Illinois']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We'll discuss some of the quirks of Pandas indexing and slicing in [Data Indexing and Selection](03.02-Data-Indexing-and-Selection.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Constructing Series objects\n",
"\n",
"We've already seen a few ways of constructing a Pandas ``Series`` from scratch; all of them are some version of the following:\n",
"\n",
"```python\n",
">>> pd.Series(data, index=index)\n",
"```\n",
"\n",
"where ``index`` is an optional argument, and ``data`` can be one of many entities.\n",
"\n",
"For example, ``data`` can be a list or NumPy array, in which case ``index`` defaults to an integer sequence:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0 2\n",
"1 4\n",
"2 6\n",
"dtype: int64"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.Series([2, 4, 6])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"``data`` can be a scalar, which is repeated to fill the specified index:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"100 5\n",
"200 5\n",
"300 5\n",
"dtype: int64"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.Series(5, index=[100, 200, 300])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"``data`` can be a dictionary, in which ``index`` defaults to the sorted dictionary keys:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1 b\n",
"2 a\n",
"3 c\n",
"dtype: object"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.Series({2:'a', 1:'b', 3:'c'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In each case, the index can be explicitly set if a different result is preferred:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3 c\n",
"2 a\n",
"dtype: object"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.Series({2:'a', 1:'b', 3:'c'}, index=[3, 2])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that in this case, the ``Series`` is populated only with the explicitly identified keys."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Pandas DataFrame Object\n",
"\n",
"The next fundamental structure in Pandas is the ``DataFrame``.\n",
"Like the ``Series`` object discussed in the previous section, the ``DataFrame`` can be thought of either as a generalization of a NumPy array, or as a specialization of a Python dictionary.\n",
"We'll now take a look at each of these perspectives."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### DataFrame as a generalized NumPy array\n",
"If a ``Series`` is an analog of a one-dimensional array with flexible indices, a ``DataFrame`` is an analog of a two-dimensional array with both flexible row indices and flexible column names.\n",
"Just as you might think of a two-dimensional array as an ordered sequence of aligned one-dimensional columns, you can think of a ``DataFrame`` as a sequence of aligned ``Series`` objects.\n",
"Here, by \"aligned\" we mean that they share the same index.\n",
"\n",
"To demonstrate this, let's first construct a new ``Series`` listing the area of each of the five states discussed in the previous section:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"California 423967\n",
"Florida 170312\n",
"Illinois 149995\n",
"New York 141297\n",
"Texas 695662\n",
"dtype: int64"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"area_dict = {'California': 423967, 'Texas': 695662, 'New York': 141297,\n",
" 'Florida': 170312, 'Illinois': 149995}\n",
"area = pd.Series(area_dict)\n",
"area"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we have this along with the ``population`` Series from before, we can use a dictionary to construct a single two-dimensional object containing this information:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>area</th>\n",
" <th>population</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>California</th>\n",
" <td>423967</td>\n",
" <td>38332521</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Florida</th>\n",
" <td>170312</td>\n",
" <td>19552860</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Illinois</th>\n",
" <td>149995</td>\n",
" <td>12882135</td>\n",
" </tr>\n",
" <tr>\n",
" <th>New York</th>\n",
" <td>141297</td>\n",
" <td>19651127</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Texas</th>\n",
" <td>695662</td>\n",
" <td>26448193</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" area population\n",
"California 423967 38332521\n",
"Florida 170312 19552860\n",
"Illinois 149995 12882135\n",
"New York 141297 19651127\n",
"Texas 695662 26448193"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"states = pd.DataFrame({'population': population,\n",
" 'area': area})\n",
"states"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Like the ``Series`` object, the ``DataFrame`` has an ``index`` attribute that gives access to the index labels:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Index(['California', 'Florida', 'Illinois', 'New York', 'Texas'], dtype='object')"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"states.index"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Additionally, the ``DataFrame`` has a ``columns`` attribute, which is an ``Index`` object holding the column labels:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Index(['area', 'population'], dtype='object')"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"states.columns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thus the ``DataFrame`` can be thought of as a generalization of a two-dimensional NumPy array, where both the rows and columns have a generalized index for accessing the data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### DataFrame as specialized dictionary\n",
"\n",
"Similarly, we can also think of a ``DataFrame`` as a specialization of a dictionary.\n",
"Where a dictionary maps a key to a value, a ``DataFrame`` maps a column name to a ``Series`` of column data.\n",
"For example, asking for the ``'area'`` attribute returns the ``Series`` object containing the areas we saw earlier:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"California 423967\n",
"Florida 170312\n",
"Illinois 149995\n",
"New York 141297\n",
"Texas 695662\n",
"Name: area, dtype: int64"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"states['area']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice the potential point of confusion here: in a two-dimesnional NumPy array, ``data[0]`` will return the first *row*. For a ``DataFrame``, ``data['col0']`` will return the first *column*.\n",
"Because of this, it is probably better to think about ``DataFrame``s as generalized dictionaries rather than generalized arrays, though both ways of looking at the situation can be useful.\n",
"We'll explore more flexible means of indexing ``DataFrame``s in [Data Indexing and Selection](03.02-Data-Indexing-and-Selection.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Constructing DataFrame objects\n",
"\n",
"A Pandas ``DataFrame`` can be constructed in a variety of ways.\n",
"Here we'll give several examples."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### From a single Series object\n",
"\n",
"A ``DataFrame`` is a collection of ``Series`` objects, and a single-column ``DataFrame`` can be constructed from a single ``Series``:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>population</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>California</th>\n",
" <td>38332521</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Florida</th>\n",
" <td>19552860</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Illinois</th>\n",
" <td>12882135</td>\n",
" </tr>\n",
" <tr>\n",
" <th>New York</th>\n",
" <td>19651127</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Texas</th>\n",
" <td>26448193</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" population\n",
"California 38332521\n",
"Florida 19552860\n",
"Illinois 12882135\n",
"New York 19651127\n",
"Texas 26448193"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(population, columns=['population'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### From a list of dicts\n",
"\n",
"Any list of dictionaries can be made into a ``DataFrame``.\n",
"We'll use a simple list comprehension to create some data:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>a</th>\n",
" <th>b</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2</td>\n",
" <td>4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" a b\n",
"0 0 0\n",
"1 1 2\n",
"2 2 4"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = [{'a': i, 'b': 2 * i}\n",
" for i in range(3)]\n",
"pd.DataFrame(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Even if some keys in the dictionary are missing, Pandas will fill them in with ``NaN`` (i.e., \"not a number\") values:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>a</th>\n",
" <th>b</th>\n",
" <th>c</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>2</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>NaN</td>\n",
" <td>3</td>\n",
" <td>4.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" a b c\n",
"0 1.0 2 NaN\n",
"1 NaN 3 4.0"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame([{'a': 1, 'b': 2}, {'b': 3, 'c': 4}])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### From a dictionary of Series objects\n",
"\n",
"As we saw before, a ``DataFrame`` can be constructed from a dictionary of ``Series`` objects as well:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>area</th>\n",
" <th>population</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>California</th>\n",
" <td>423967</td>\n",
" <td>38332521</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Florida</th>\n",
" <td>170312</td>\n",
" <td>19552860</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Illinois</th>\n",
" <td>149995</td>\n",
" <td>12882135</td>\n",
" </tr>\n",
" <tr>\n",
" <th>New York</th>\n",
" <td>141297</td>\n",
" <td>19651127</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Texas</th>\n",
" <td>695662</td>\n",
" <td>26448193</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" area population\n",
"California 423967 38332521\n",
"Florida 170312 19552860\n",
"Illinois 149995 12882135\n",
"New York 141297 19651127\n",
"Texas 695662 26448193"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame({'population': population,\n",
" 'area': area})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### From a two-dimensional NumPy array\n",
"\n",
"Given a two-dimensional array of data, we can create a ``DataFrame`` with any specified column and index names.\n",
"If omitted, an integer index will be used for each:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>foo</th>\n",
" <th>bar</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>a</th>\n",
" <td>0.865257</td>\n",
" <td>0.213169</td>\n",
" </tr>\n",
" <tr>\n",
" <th>b</th>\n",
" <td>0.442759</td>\n",
" <td>0.108267</td>\n",
" </tr>\n",
" <tr>\n",
" <th>c</th>\n",
" <td>0.047110</td>\n",
" <td>0.905718</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" foo bar\n",
"a 0.865257 0.213169\n",
"b 0.442759 0.108267\n",
"c 0.047110 0.905718"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(np.random.rand(3, 2),\n",
" columns=['foo', 'bar'],\n",
" index=['a', 'b', 'c'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### From a NumPy structured array\n",
"\n",
"We covered structured arrays in [Structured Data: NumPy's Structured Arrays](02.09-Structured-Data-NumPy.ipynb).\n",
"A Pandas ``DataFrame`` operates much like a structured array, and can be created directly from one:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([(0, 0.0), (0, 0.0), (0, 0.0)], \n",
" dtype=[('A', '<i8'), ('B', '<f8')])"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = np.zeros(3, dtype=[('A', 'i8'), ('B', 'f8')])\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>A</th>\n",
" <th>B</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" A B\n",
"0 0 0.0\n",
"1 0 0.0\n",
"2 0 0.0"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Pandas Index Object\n",
"\n",
"We have seen here that both the ``Series`` and ``DataFrame`` objects contain an explicit *index* that lets you reference and modify data.\n",
"This ``Index`` object is an interesting structure in itself, and it can be thought of either as an *immutable array* or as an *ordered set* (technically a multi-set, as ``Index`` objects may contain repeated values).\n",
"Those views have some interesting consequences in the operations available on ``Index`` objects.\n",
"As a simple example, let's construct an ``Index`` from a list of integers:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Int64Index([2, 3, 5, 7, 11], dtype='int64')"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ind = pd.Index([2, 3, 5, 7, 11])\n",
"ind"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Index as immutable array\n",
"\n",
"The ``Index`` in many ways operates like an array.\n",
"For example, we can use standard Python indexing notation to retrieve values or slices:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ind[1]"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Int64Index([2, 5, 11], dtype='int64')"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ind[::2]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"``Index`` objects also have many of the attributes familiar from NumPy arrays:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5 (5,) 1 int64\n"
]
}
],
"source": [
"print(ind.size, ind.shape, ind.ndim, ind.dtype)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One difference between ``Index`` objects and NumPy arrays is that indices are immutablethat is, they cannot be modified via the normal means:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "TypeError",
"evalue": "Index does not support mutable operations",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-34-40e631c82e8a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mind\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m/Users/jakevdp/anaconda/lib/python3.5/site-packages/pandas/indexes/base.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 1243\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1244\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__setitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1245\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Index does not support mutable operations\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1246\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1247\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__getitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mTypeError\u001b[0m: Index does not support mutable operations"
]
}
],
"source": [
"ind[1] = 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This immutability makes it safer to share indices between multiple ``DataFrame``s and arrays, without the potential for side effects from inadvertent index modification."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Index as ordered set\n",
"\n",
"Pandas objects are designed to facilitate operations such as joins across datasets, which depend on many aspects of set arithmetic.\n",
"The ``Index`` object follows many of the conventions used by Python's built-in ``set`` data structure, so that unions, intersections, differences, and other combinations can be computed in a familiar way:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"indA = pd.Index([1, 3, 5, 7, 9])\n",
"indB = pd.Index([2, 3, 5, 7, 11])"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Int64Index([3, 5, 7], dtype='int64')"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"indA & indB # intersection"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Int64Index([1, 2, 3, 5, 7, 9, 11], dtype='int64')"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"indA | indB # union"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Int64Index([1, 2, 9, 11], dtype='int64')"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"indA ^ indB # symmetric difference"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These operations may also be accessed via object methods, for example ``indA.intersection(indB)``."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!--NAVIGATION-->\n",
"< [Data Manipulation with Pandas](03.00-Introduction-to-Pandas.ipynb) | [Contents](Index.ipynb) | [Data Indexing and Selection](03.02-Data-Indexing-and-Selection.ipynb) >"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}