{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "title: pandas练习-多层索引的创建和各种操作(multiindex)第二部分\n", "date: 2019-01-24 20:17:55\n", "tags: [pandas]\n", "toc: true\n", "xiongzhang: true\n", "xiongzhang_images: [main.jpg]\n", "\n", "---\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 使用切片(slicers)\n", "\n", "你可以使用切片来选择MultiIndex, `slice`是python内置的函数(其实是一个类), 他的用法是这样的:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['b', 'd', 'f']" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alist = list('abcdefg' * 3)\n", "selector = slice(1, 6, 2)\n", "alist[selector]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "我们可以使用`slice`来选择MultiIndex。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "下面先创建一个DataFrame:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lvl0ab
lvl1barfoobahfoo
A0B0C0D01032
D15476
C1D0981110
D113121514
C2D017161918
\n", "
" ], "text/plain": [ "lvl0 a b \n", "lvl1 bar foo bah foo\n", "A0 B0 C0 D0 1 0 3 2\n", " D1 5 4 7 6\n", " C1 D0 9 8 11 10\n", " D1 13 12 15 14\n", " C2 D0 17 16 19 18" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "import numpy as np\n", "def mklbl(prefix,n):\n", " return [\"%s%s\" % (prefix,i) for i in range(n)]\n", "\n", "\n", "miindex = pd.MultiIndex.from_product([mklbl('A',4),\n", " mklbl('B',2),\n", " mklbl('C',4),\n", " mklbl('D',2)])\n", "\n", "\n", "micolumns = pd.MultiIndex.from_tuples([('a','foo'),('a','bar'),\n", " ('b','foo'),('b','bah')],\n", " names=['lvl0', 'lvl1'])\n", "\n", "\n", "dfmi = pd.DataFrame(np.arange(len(miindex)*len(micolumns)).reshape((len(miindex),len(micolumns))),\n", " index=miindex,\n", " columns=micolumns).sort_index().sort_index(axis=1)\n", "\n", "dfmi.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "下面我们需要选择出MultiIndex第一层为A1或A2或A3, 第二层不做选择, 第三层只包括C1和C3的行:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lvl0ab
lvl1barfoobahfoo
A1B0C1D073727574
D177767978
C3D089889190
D193929594
B1C1D0105104107106
D1109108111110
C3D0121120123122
D1125124127126
A2B0C1D0137136139138
D1141140143142
C3D0153152155154
D1157156159158
B1C1D0169168171170
D1173172175174
C3D0185184187186
D1189188191190
A3B0C1D0201200203202
D1205204207206
C3D0217216219218
D1221220223222
B1C1D0233232235234
D1237236239238
C3D0249248251250
D1253252255254
\n", "
" ], "text/plain": [ "lvl0 a b \n", "lvl1 bar foo bah foo\n", "A1 B0 C1 D0 73 72 75 74\n", " D1 77 76 79 78\n", " C3 D0 89 88 91 90\n", " D1 93 92 95 94\n", " B1 C1 D0 105 104 107 106\n", " D1 109 108 111 110\n", " C3 D0 121 120 123 122\n", " D1 125 124 127 126\n", "A2 B0 C1 D0 137 136 139 138\n", " D1 141 140 143 142\n", " C3 D0 153 152 155 154\n", " D1 157 156 159 158\n", " B1 C1 D0 169 168 171 170\n", " D1 173 172 175 174\n", " C3 D0 185 184 187 186\n", " D1 189 188 191 190\n", "A3 B0 C1 D0 201 200 203 202\n", " D1 205 204 207 206\n", " C3 D0 217 216 219 218\n", " D1 221 220 223 222\n", " B1 C1 D0 233 232 235 234\n", " D1 237 236 239 238\n", " C3 D0 249 248 251 250\n", " D1 253 252 255 254" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfmi.loc[(slice('A1', 'A3'), slice(None), ['C1', 'C3']), :]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "你还可以使用`pandas.IndexSlic`类来实现类似的选择:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lvl0ab
lvl1barfoobahfoo
A1B0C1D073727574
D177767978
C3D089889190
D193929594
B1C1D0105104107106
D1109108111110
C3D0121120123122
D1125124127126
A2B0C1D0137136139138
D1141140143142
C3D0153152155154
D1157156159158
B1C1D0169168171170
D1173172175174
C3D0185184187186
D1189188191190
A3B0C1D0201200203202
D1205204207206
C3D0217216219218
D1221220223222
B1C1D0233232235234
D1237236239238
C3D0249248251250
D1253252255254
\n", "
" ], "text/plain": [ "lvl0 a b \n", "lvl1 bar foo bah foo\n", "A1 B0 C1 D0 73 72 75 74\n", " D1 77 76 79 78\n", " C3 D0 89 88 91 90\n", " D1 93 92 95 94\n", " B1 C1 D0 105 104 107 106\n", " D1 109 108 111 110\n", " C3 D0 121 120 123 122\n", " D1 125 124 127 126\n", "A2 B0 C1 D0 137 136 139 138\n", " D1 141 140 143 142\n", " C3 D0 153 152 155 154\n", " D1 157 156 159 158\n", " B1 C1 D0 169 168 171 170\n", " D1 173 172 175 174\n", " C3 D0 185 184 187 186\n", " D1 189 188 191 190\n", "A3 B0 C1 D0 201 200 203 202\n", " D1 205 204 207 206\n", " C3 D0 217 216 219 218\n", " D1 221 220 223 222\n", " B1 C1 D0 233 232 235 234\n", " D1 237 236 239 238\n", " C3 D0 249 248 251 250\n", " D1 253 252 255 254" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "idx = pd.IndexSlice\n", "\n", "dfmi.loc[idx['A1': 'A3', :, ['C1', 'C3']], :]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "同样是上面的例子, 我们可以选择出列索引第二层为bar的列:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lvl0ab
lvl1foofoo
A1B0C1D07274
D17678
C3D08890
D19294
B1C1D0104106
D1108110
C3D0120122
D1124126
A2B0C1D0136138
D1140142
C3D0152154
D1156158
B1C1D0168170
D1172174
C3D0184186
D1188190
A3B0C1D0200202
D1204206
C3D0216218
D1220222
B1C1D0232234
D1236238
C3D0248250
D1252254
\n", "
" ], "text/plain": [ "lvl0 a b\n", "lvl1 foo foo\n", "A1 B0 C1 D0 72 74\n", " D1 76 78\n", " C3 D0 88 90\n", " D1 92 94\n", " B1 C1 D0 104 106\n", " D1 108 110\n", " C3 D0 120 122\n", " D1 124 126\n", "A2 B0 C1 D0 136 138\n", " D1 140 142\n", " C3 D0 152 154\n", " D1 156 158\n", " B1 C1 D0 168 170\n", " D1 172 174\n", " C3 D0 184 186\n", " D1 188 190\n", "A3 B0 C1 D0 200 202\n", " D1 204 206\n", " C3 D0 216 218\n", " D1 220 222\n", " B1 C1 D0 232 234\n", " D1 236 238\n", " C3 D0 248 250\n", " D1 252 254" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfmi.loc[idx['A1': 'A3', :, ['C1', 'C3']], idx[:, 'foo']]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "另外, 我们可以使用布尔的蒙版来配合`IndexSlice`选择数据, 下面我们选择出foo列的数值小于100的行:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lvl0ab
lvl1foofoo
A0B0C1D0810
D11214
C2D01618
D12022
B1C1D04042
D14446
C2D04850
D15254
A1B0C1D07274
D17678
C2D08082
D18486
\n", "
" ], "text/plain": [ "lvl0 a b\n", "lvl1 foo foo\n", "A0 B0 C1 D0 8 10\n", " D1 12 14\n", " C2 D0 16 18\n", " D1 20 22\n", " B1 C1 D0 40 42\n", " D1 44 46\n", " C2 D0 48 50\n", " D1 52 54\n", "A1 B0 C1 D0 72 74\n", " D1 76 78\n", " C2 D0 80 82\n", " D1 84 86" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask = (dfmi[('a', 'foo')] < 100) & (dfmi[('b', 'foo')] < 100)\n", "\n", "dfmi.loc[idx[mask, :, ['C1', 'C2']], idx[:, 'foo']]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 按索引聚合数据和数据对齐\n", "\n", "在多层索引中, 我们可以依据某一层进行数据聚合, 比如求和, 求均值, 下面我们先来创建一个dataframe:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
oney-0.6344070.272985
x-0.5469910.001771
zeroy1.801089-1.132311
x0.2131002.339203
\n", "
" ], "text/plain": [ " 0 1\n", "one y -0.634407 0.272985\n", " x -0.546991 0.001771\n", "zero y 1.801089 -1.132311\n", " x 0.213100 2.339203" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "midx = pd.MultiIndex(levels=[['zero', 'one'], ['x','y']],\n", " labels=[[1,1,0,0],[1,0,1,0]])\n", "\n", "\n", "df = pd.DataFrame(np.random.randn(4,2), index=midx)\n", "\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "求第一层索引的均值:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
one-0.5906990.137378
zero1.0070940.603446
\n", "
" ], "text/plain": [ " 0 1\n", "one -0.590699 0.137378\n", "zero 1.007094 0.603446" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = df.mean(level=0)\n", "df2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果我们想用均值替换原先的所有值, 我们可以恢复到原始数据的形状和索引:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
oney-0.5906990.137378
x-0.5906990.137378
zeroy1.0070940.603446
x1.0070940.603446
\n", "
" ], "text/plain": [ " 0 1\n", "one y -0.590699 0.137378\n", " x -0.590699 0.137378\n", "zero y 1.007094 0.603446\n", " x 1.007094 0.603446" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df3 = df2.reindex(df.index, level=0)\n", "df3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上面就是一个数据对齐的过程, df2的索引和df的索引按照第一层对齐, 也就是[one, zero]对齐, 假如不对齐, 我们会得到什么结果?" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
oneyNaNNaN
xNaNNaN
zeroyNaNNaN
xNaNNaN
\n", "
" ], "text/plain": [ " 0 1\n", "one y NaN NaN\n", " x NaN NaN\n", "zero y NaN NaN\n", " x NaN NaN" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df4 = df2.reindex(df.index)\n", "df4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "我们可以使用更直观的方式去对齐数据:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
oney-0.5906990.137378
x-0.5906990.137378
zeroy1.0070940.603446
x1.0070940.603446
\n", "
" ], "text/plain": [ " 0 1\n", "one y -0.590699 0.137378\n", " x -0.590699 0.137378\n", "zero y 1.007094 0.603446\n", " x 1.007094 0.603446" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_a, df2_a = df.align(df2, level=0)\n", "df2_a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "需要注意的是, 上面的方法可能会更改df和df2, 所以有两个返回值。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 交换多层索引的层序\n", "\n", "直接看例子就好了, 对比交换前后的index:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
oney-0.6344070.272985
x-0.5469910.001771
zeroy1.801089-1.132311
x0.2131002.339203
\n", "
" ], "text/plain": [ " 0 1\n", "one y -0.634407 0.272985\n", " x -0.546991 0.001771\n", "zero y 1.801089 -1.132311\n", " x 0.213100 2.339203" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
yone-0.6344070.272985
xone-0.5469910.001771
yzero1.801089-1.132311
xzero0.2131002.339203
\n", "
" ], "text/plain": [ " 0 1\n", "y one -0.634407 0.272985\n", "x one -0.546991 0.001771\n", "y zero 1.801089 -1.132311\n", "x zero 0.213100 2.339203" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.swaplevel(0, 1, axis=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "另外, 可以使用reorder_levels达到相同的目的, 只不过它可以一次性修改多层index的次序:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
yone-0.6344070.272985
xone-0.5469910.001771
yzero1.801089-1.132311
xzero0.2131002.339203
\n", "
" ], "text/plain": [ " 0 1\n", "y one -0.634407 0.272985\n", "x one -0.546991 0.001771\n", "y zero 1.801089 -1.132311\n", "x zero 0.213100 2.339203" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.reorder_levels([1, 0], axis=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 排序\n", "\n", "我们可以使用sort_index对索引进行排序。" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "baz one 0.035299\n", "foo one -1.021257\n", "baz two -0.225705\n", "foo two -0.369259\n", "bar one -0.681788\n", " two 0.873609\n", "qux two 0.325956\n", " one -1.330222\n", "dtype: float64" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import random; \n", "\n", "arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],\n", " ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]\n", " \n", "\n", "tuples = list(zip(*arrays))\n", "random.shuffle(tuples)\n", "index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])\n", "s = pd.Series(np.random.randn(8), index=pd.MultiIndex.from_tuples(tuples))\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "默认情况下, sort_index可以逐层排序, 首先排level=0的层:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "bar one -0.681788\n", " two 0.873609\n", "baz one 0.035299\n", " two -0.225705\n", "foo one -1.021257\n", " two -0.369259\n", "qux one -1.330222\n", " two 0.325956\n", "dtype: float64" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.sort_index()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "但是我们可以选择只对某一层排序:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "bar one -0.681788\n", "baz one 0.035299\n", "foo one -1.021257\n", "qux one -1.330222\n", "bar two 0.873609\n", "baz two -0.225705\n", "foo two -0.369259\n", "qux two 0.325956\n", "dtype: float64" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.sort_index(level=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果多层索引设置了names属性, 我们可以使用名称作为参数:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "a b \n", "bar one -0.681788\n", "baz one 0.035299\n", "foo one -1.021257\n", "qux one -1.330222\n", "bar two 0.873609\n", "baz two -0.225705\n", "foo two -0.369259\n", "qux two 0.325956\n", "dtype: float64" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.index.names=['a', 'b']\n", "s.sort_index(level='b')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "除了对索引进行排序, 我们还可以对DataFrame.columns排序, 先来看一下我们的数据:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
onezero
yxyx
0-0.634407-0.5469911.8010890.213100
10.2729850.001771-1.1323112.339203
\n", "
" ], "text/plain": [ " one zero \n", " y x y x\n", "0 -0.634407 -0.546991 1.801089 0.213100\n", "1 0.272985 0.001771 -1.132311 2.339203" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dft = df.T\n", "dft" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
onezeroonezero
xxyy
0-0.5469910.213100-0.6344071.801089
10.0017712.3392030.272985-1.132311
\n", "
" ], "text/plain": [ " one zero one zero\n", " x x y y\n", "0 -0.546991 0.213100 -0.634407 1.801089\n", "1 0.001771 2.339203 0.272985 -1.132311" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dft.sort_index(level=1, axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "index排序后有一个好处, 就是你可以使用切片来选择数据, 但是如果index没有排序, 你可能会遇到错误:" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "ename": "UnsortedIndexError", "evalue": "'Key length (2) was greater than MultiIndex lexsort depth (0)'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mUnsortedIndexError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'baz'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'one'\u001b[0m \u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'bar'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'one'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexing.py\u001b[0m in \u001b[0;36m__getitem__\u001b[1;34m(self, key)\u001b[0m\n\u001b[0;32m 1476\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1477\u001b[0m \u001b[0mmaybe_callable\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcom\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_apply_if_callable\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1478\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_getitem_axis\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmaybe_callable\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0maxis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1479\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1480\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_is_scalar_access\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexing.py\u001b[0m in \u001b[0;36m_getitem_axis\u001b[1;34m(self, key, axis)\u001b[0m\n\u001b[0;32m 1864\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mslice\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1865\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_validate_key\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1866\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_slice_axis\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0maxis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1867\u001b[0m \u001b[1;32melif\u001b[0m \u001b[0mcom\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mis_bool_indexer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1868\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_getbool_axis\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0maxis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexing.py\u001b[0m in \u001b[0;36m_get_slice_axis\u001b[1;34m(self, slice_obj, axis)\u001b[0m\n\u001b[0;32m 1509\u001b[0m \u001b[0mlabels\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_axis\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maxis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1510\u001b[0m indexer = labels.slice_indexer(slice_obj.start, slice_obj.stop,\n\u001b[1;32m-> 1511\u001b[1;33m slice_obj.step, kind=self.name)\n\u001b[0m\u001b[0;32m 1512\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1513\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mindexer\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mslice\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexes\\base.py\u001b[0m in \u001b[0;36mslice_indexer\u001b[1;34m(self, start, end, step, kind)\u001b[0m\n\u001b[0;32m 4105\u001b[0m \"\"\"\n\u001b[0;32m 4106\u001b[0m start_slice, end_slice = self.slice_locs(start, end, step=step,\n\u001b[1;32m-> 4107\u001b[1;33m kind=kind)\n\u001b[0m\u001b[0;32m 4108\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4109\u001b[0m \u001b[1;31m# return a slice\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexes\\multi.py\u001b[0m in \u001b[0;36mslice_locs\u001b[1;34m(self, start, end, step, kind)\u001b[0m\n\u001b[0;32m 2144\u001b[0m \u001b[1;31m# This function adds nothing to its parent implementation (the magic\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2145\u001b[0m \u001b[1;31m# happens in get_slice_bound method), but it adds meaningful doc.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 2146\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mMultiIndex\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mslice_locs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstep\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkind\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mkind\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2147\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2148\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_partial_tup_index\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtup\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mside\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'left'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexes\\base.py\u001b[0m in \u001b[0;36mslice_locs\u001b[1;34m(self, start, end, step, kind)\u001b[0m\n\u001b[0;32m 4306\u001b[0m \u001b[0mstart_slice\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4307\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mstart\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 4308\u001b[1;33m \u001b[0mstart_slice\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_slice_bound\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'left'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkind\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4309\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mstart_slice\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4310\u001b[0m \u001b[0mstart_slice\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexes\\multi.py\u001b[0m in \u001b[0;36mget_slice_bound\u001b[1;34m(self, label, side, kind)\u001b[0m\n\u001b[0;32m 2088\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlabel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2089\u001b[0m \u001b[0mlabel\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlabel\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 2090\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_partial_tup_index\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlabel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mside\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mside\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2091\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2092\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mslice_locs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstart\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstep\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkind\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\mysites\\deeplearning.ai-master\\.env\\lib\\site-packages\\pandas\\core\\indexes\\multi.py\u001b[0m in \u001b[0;36m_partial_tup_index\u001b[1;34m(self, tup, side)\u001b[0m\n\u001b[0;32m 2151\u001b[0m \u001b[1;34m'Key length (%d) was greater than MultiIndex'\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2152\u001b[0m \u001b[1;34m' lexsort depth (%d)'\u001b[0m \u001b[1;33m%\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 2153\u001b[1;33m (len(tup), self.lexsort_depth))\n\u001b[0m\u001b[0;32m 2154\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2155\u001b[0m \u001b[0mn\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtup\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mUnsortedIndexError\u001b[0m: 'Key length (2) was greater than MultiIndex lexsort depth (0)'" ] } ], "source": [ "s.loc[('baz', 'one' ): ('bar', 'one')]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "我们可以使用is_lexsorted来判断是否经过了排序:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.index.is_lexsorted()" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "a b \n", "bar one -0.681788\n", " two 0.873609\n", "baz one 0.035299\n", "dtype: float64" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ss = s.sort_index()\n", "ss.loc[('bar', 'one' ): ('baz', 'one')]" ] } ], "metadata": { "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.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }