<jupyter_start><jupyter_text>Getting Started with pandas pandas是本书后续内容的首选库。它含有使数据清洗和分析工作变得更快更简单的数据结构和操作工具。pandas经常和其它工具一同使用，如数值计算工具NumPy和SciPy，分析库statsmodels和scikit-learn，和数据可视化库matplotlib。pandas是基于NumPy数组构建的，特别是基于数组的函数和不使用for循环的数据处理。虽然pandas采用了大量的NumPy编码风格，但二者最大的不同是pandas是专门为处理表格和混杂数据设计的。而NumPy更适合处理统一的数值数组数据。自从2010年pandas开源以来，pandas逐渐成长为一个非常大的库，应用于许多真实案例。开发者社区已经有了800个独立的贡献者，他们在解决日常数据问题的同时为这个项目提供贡献。在本书后续部分中，我将使用下面这样的pandas引入约定:<jupyter_code>import pandas as pd<jupyter_output><empty_output><jupyter_text>因此，只要你在代码中看到pd.，就得想到这是pandas。因为Series和DataFrame用的次数非常多，所以将其引入本地命名空间中会更方便：<jupyter_code>from pandas import Series, DataFrame
import numpy as np
np.random.seed(12345)
import matplotlib.pyplot as plt
plt.rc('figure', figsize=(10, 6))
PREVIOUS_MAX_ROWS = pd.options.display.max_rows
pd.options.display.max_rows = 20
np.set_printoptions(precision=4, suppress=True)<jupyter_output><empty_output><jupyter_text>Introduction to pandas Data Structures 要使用pandas，你首先就得熟悉它的两个主要数据结构：Series和DataFrame。虽然它们并不能解决所有问题，但它们为大多数应用提供了一种可靠的、易于使用的基础。  Series Series是一种类似于一维数组的对象，它由一组数据（各种NumPy数据类型）以及一组与之相关的数据标签（即索引）组成。仅由一组数据即可产生最简单的Series：<jupyter_code>obj = pd.Series([4, 7, -5, 3])
obj<jupyter_output><empty_output><jupyter_text>Series的字符串表现形式为：索引在左边，值在右边。由于我们没有为数据指定索引，于是会自动创建一个0到N-1（N为数据的长度）的整数型索引。你可以通过Series 的values和index属性获取其数组表示形式和索引对象：<jupyter_code>obj.values
obj.index  # like range(4)<jupyter_output><empty_output><jupyter_text>通常，我们希望所创建的Series带有一个可以对各个数据点进行标记的索引：<jupyter_code>obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
obj2
obj2.index<jupyter_output><empty_output><jupyter_text>与普通NumPy数组相比，你可以通过索引的方式选取Series中的单个或一组值：<jupyter_code>obj2['a']
obj2['d'] = 6
obj2[['c', 'a', 'd']]<jupyter_output><empty_output><jupyter_text>['c', 'a', 'd']是索引列表，即使它包含的是字符串而不是整数。使用NumPy函数或类似NumPy的运算（如根据布尔型数组进行过滤、标量乘法、应用数学函数等）都会保留索引值的链接：<jupyter_code>obj2[obj2 > 0]
obj2 * 2
np.exp(obj2)<jupyter_output><empty_output><jupyter_text>还可以将Series看成是一个定长的有序字典，因为它是索引值到数据值的一个映射。它可以用在许多原本需要字典参数的函数中：<jupyter_code>'b' in obj2
'e' in obj2<jupyter_output><empty_output><jupyter_text>如果数据被存放在一个Python字典中，也可以直接通过这个字典来创建Series：<jupyter_code>sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj3 = pd.Series(sdata)
obj3<jupyter_output><empty_output><jupyter_text>如果只传入一个字典，则结果Series中的索引就是原字典的键（有序排列）。你可以传入排好序的字典的键以改变顺序：<jupyter_code>states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = pd.Series(sdata, index=states)
obj4<jupyter_output><empty_output><jupyter_text>在这个例子中，sdata中跟states索引相匹配的那3个值会被找出来并放到相应的位置上，但由于"California"所对应的sdata值找不到，所以其结果就为NaN（即“非数字”（not a number），在pandas中，它用于表示缺失或NA值）。因为‘Utah’不在states中，它被从结果中除去。我将使用缺失（missing）或NA表示缺失数据。pandas的isnull和notnull函数可用于检测缺失数据：<jupyter_code>pd.isnull(obj4)
pd.notnull(obj4)<jupyter_output><empty_output><jupyter_text>Series也有类似的实例方法：<jupyter_code>obj4.isnull()<jupyter_output><empty_output><jupyter_text>我将在第7章详细讲解如何处理缺失数据。对于许多应用而言，Series最重要的一个功能是，它会根据运算的索引标签自动对齐数据：<jupyter_code>obj3
obj4
obj3 + obj4<jupyter_output><empty_output><jupyter_text>数据对齐功能将在后面详细讲解。如果你使用过数据库，你可以认为是类似join的操作。Series对象本身及其索引都有一个name属性，该属性跟pandas其他的关键功能关系非常密切：<jupyter_code>obj4.name = 'population'
obj4.index.name = 'state'
obj4<jupyter_output><empty_output><jupyter_text>Series的索引可以通过赋值的方式就地修改：<jupyter_code>obj
obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
obj<jupyter_output><empty_output><jupyter_text>DataFrame DataFrame是一个表格型的数据结构，它含有一组有序的列，每列可以是不同的值类型（数值、字符串、布尔值等）。DataFrame既有行索引也有列索引，它可以被看做由Series组成的字典（共用同一个索引）。DataFrame中的数据是以一个或多个二维块存放的（而不是列表、字典或别的一维数据结构）。有关DataFrame内部的技术细节远远超出了本书所讨论的范围。> 笔记：虽然DataFrame是以二维结构保存数据的，但你仍然可以轻松地将其表示为更高维度的数据（层次化索引的表格型结构，这是pandas中许多高级数据处理功能的关键要素，我们会在第8章讨论这个问题）。建DataFrame的办法有很多，最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典：<jupyter_code>data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002, 2003],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)<jupyter_output><empty_output><jupyter_text>结果DataFrame会自动加上索引（跟Series一样），且全部列会被有序排列：<jupyter_code>frame<jupyter_output><empty_output><jupyter_text>如果你使用的是Jupyter notebook，pandas DataFrame对象会以对浏览器友好的HTML表格的方式呈现。对于特别大的DataFrame，head方法会选取前五行：<jupyter_code>frame.head()<jupyter_output><empty_output><jupyter_text>如果指定了列序列，则DataFrame的列就会按照指定顺序进行排列：<jupyter_code>pd.DataFrame(data, columns=['year', 'state', 'pop'])<jupyter_output><empty_output><jupyter_text>如果传入的列在数据中找不到，就会在结果中产生缺失值：<jupyter_code>frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
                      index=['one', 'two', 'three', 'four',
                             'five', 'six'])
print(frame2)
frame2.columns<jupyter_output>year   state  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN
six    2003  Nevada  3.2  NaN<jupyter_text>通过类似字典标记的方式或属性的方式，可以将DataFrame的列获取为一个Series：<jupyter_code>frame2['state']
frame2.year<jupyter_output><empty_output><jupyter_text>> 笔记：IPython提供了类似属性的访问（即frame2.year）和tab补全。frame2[column]适用于任何列的名，但是frame2.column只有在列名是一个合理的Python变量名时才适用。注意，返回的Series拥有原DataFrame相同的索引，且其name属性也已经被相应地设置好了。行也可以通过位置或名称的方式进行获取，比如用loc属性（稍后将对此进行详细讲解）：<jupyter_code>frame2.loc['three']<jupyter_output><empty_output><jupyter_text>列可以通过赋值的方式进行修改。例如，我们可以给那个空的"debt"列赋上一个标量值或一组值：<jupyter_code>frame2['debt'] = 16.5
frame2
frame2['debt'] = np.arange(6.)
frame2<jupyter_output><empty_output><jupyter_text>将列表或数组赋值给某个列时，其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series，就会精确匹配DataFrame的索引，所有的空位都将被填上缺失值：<jupyter_code>val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
frame2['debt'] = val
frame2<jupyter_output><empty_output><jupyter_text>为不存在的列赋值会创建出一个新列。关键字del用于删除列。作为del的例子，我先添加一个新的布尔值的列，state是否为'Ohio'：<jupyter_code>frame2['eastern'] = frame2.state == 'Ohio'
frame2<jupyter_output><empty_output><jupyter_text>> 注意：不能用frame2.eastern创建新的列。del方法可以用来删除这列：<jupyter_code>del frame2['eastern']
frame2.columns<jupyter_output><empty_output><jupyter_text>> 注意：通过索引方式返回的列只是相应数据的视图而已，并不是副本。因此，对返回的Series所做的任何就地修改全都会反映到源DataFrame上。通过Series的copy方法即可指定复制列。另一种常见的数据形式是嵌套字典：<jupyter_code>pop = {'Nevada': {2001: 2.4, 2002: 2.9},
       'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}<jupyter_output><empty_output><jupyter_text>如果嵌套字典传给DataFrame，pandas就会被解释为：外层字典的键作为列，内层键则作为行索引：<jupyter_code>frame3 = pd.DataFrame(pop)
frame3<jupyter_output><empty_output><jupyter_text>你也可以使用类似NumPy数组的方法，对DataFrame进行转置（交换行和列）：<jupyter_code>frame3.T<jupyter_output><empty_output><jupyter_text>内层字典的键会被合并、排序以形成最终的索引。如果明确指定了索引，则不会这样：<jupyter_code>pd.DataFrame(pop, index=[2001, 2002, 2003])<jupyter_output><empty_output><jupyter_text>由Series组成的字典差不多也是一样的用法：<jupyter_code>pdata = {'Ohio': frame3['Ohio'][:-1],
         'Nevada': frame3['Nevada'][:2]}
pd.DataFrame(pdata)<jupyter_output><empty_output><jupyter_text>如果设置了DataFrame的index和columns的name属性，则这些信息也会被显示出来：<jupyter_code>frame3.index.name = 'year'; frame3.columns.name = 'state'
frame3<jupyter_output><empty_output><jupyter_text>跟Series一样，values属性也会以二维ndarray的形式返回DataFrame中的数据：<jupyter_code>frame3.values<jupyter_output><empty_output><jupyter_text>如果DataFrame各列的数据类型不同，则值数组的dtype就会选用能兼容所有列的数据类型：<jupyter_code>frame2.values<jupyter_output><empty_output><jupyter_text>Index Objects pandas的索引对象负责管理轴标签和其他元数据（比如轴名称等）。构建Series或DataFrame时，所用到的任何数组或其他序列的标签都会被转换成一个Index：<jupyter_code>obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
index
index[1:]<jupyter_output><empty_output><jupyter_text>Index对象是不可变的，因此用户不能对其进行修改：<jupyter_code>index[1] = 'd'  # TypeError<jupyter_output><empty_output><jupyter_text>不可变可以使Index对象在多个数据结构之间安全共享：<jupyter_code>labels = pd.Index(np.arange(3))
labels
obj2 = pd.Series([1.5, -2.5, 0], index=labels)
obj2
obj2.index is labels<jupyter_output><empty_output><jupyter_text>> 注意：虽然用户不需要经常使用Index的功能，但是因为一些操作会生成包含被索引化的数据，理解它们的工作原理是很重要的。除了类似于数组，Index的功能也类似一个固定大小的集合：<jupyter_code>frame3
frame3.columns
'Ohio' in frame3.columns
2003 in frame3.index<jupyter_output><empty_output><jupyter_text>与python的集合不同，pandas的Index可以包含重复的标签：<jupyter_code>dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
dup_labels<jupyter_output><empty_output><jupyter_text>选择重复的标签，会显示所有的结果。每个索引都有一些方法和属性，它们可用于设置逻辑并回答有关该索引所包含的数据的常见问题。  Essential Functionality 本节中，我将介绍操作Series和DataFrame中的数据的基本手段。后续章节将更加深入地挖掘pandas在数据分析和处理方面的功能。本书不是pandas库的详尽文档，主要关注的是最重要的功能，那些不大常用的内容（也就是那些更深奥的内容）就交给你自己去摸索吧。  Reindexing 重新索引 pandas对象的一个重要方法是reindex，其作用是创建一个新对象，它的数据符合新的索引。看下面的例子：<jupyter_code>obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj<jupyter_output><empty_output><jupyter_text>用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存在，就引入缺失值：<jupyter_code>obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
obj2<jupyter_output><empty_output><jupyter_text>对于时间序列这样的有序数据，重新索引时可能需要做一些插值处理。method选项即可达到此目的，例如，使用ffill可以实现前向值填充：<jupyter_code>obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
obj3
obj3.reindex(range(6), method='ffill')<jupyter_output><empty_output><jupyter_text>借助DataFrame，reindex可以修改（行）索引和列。只传递一个序列时，会重新索引结果的行：|<jupyter_code>frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
                     index=['a', 'c', 'd'],
                     columns=['Ohio', 'Texas', 'California'])
frame
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
frame2<jupyter_output><empty_output><jupyter_text>列可以用columns关键字重新索引：<jupyter_code>states = ['Texas', 'Utah', 'California']
frame.reindex(columns=states)<jupyter_output><empty_output><jupyter_text>Dropping Entries from an Axis 丢弃指定轴上的项 丢弃某条轴上的一个或多个项很简单，只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑，所以drop方法返回的是一个在指定轴上删除了指定值的新对象：<jupyter_code>obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
obj
new_obj = obj.drop('c')
new_obj
obj.drop(['d', 'c'])<jupyter_output><empty_output><jupyter_text>对于DataFrame，可以删除任意轴上的索引值。为了演示，先新建一个DataFrame例子：<jupyter_code>data = pd.DataFrame(np.arange(16).reshape((4, 4)),
                    index=['Ohio', 'Colorado', 'Utah', 'New York'],
                    columns=['one', 'two', 'three', 'four'])
data<jupyter_output><empty_output><jupyter_text>用标签序列调用drop会从行标签（axis 0）删除值：<jupyter_code>data.drop(['Colorado', 'Ohio'])<jupyter_output><empty_output><jupyter_text>通过传递axis=1或axis='columns'可以删除列的值：<jupyter_code>data.drop('two', axis=1)
data.drop(['two', 'four'], axis='columns')<jupyter_output><empty_output><jupyter_text>许多函数，如drop，会修改Series或DataFrame的大小或形状，可以就地修改对象，不会返回新的对象：<jupyter_code>obj.drop('c', inplace=True)
obj<jupyter_output><empty_output><jupyter_text>小心使用inplace，它会销毁所有被删除的数据。  Indexing, Selection, and Filtering 索引、选取和过滤 Series索引（obj[...]）的工作方式类似于NumPy数组的索引，只不过Series的索引值不只是整数。下面是几个例子：<jupyter_code>obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
obj
obj['b']
obj[1]
obj[2:4]
obj[['b', 'a', 'd']]
obj[[1, 3]]
obj[obj < 2]<jupyter_output><empty_output><jupyter_text>利用标签的切片运算与普通的Python切片运算不同，其末端是包含的：<jupyter_code>obj['b':'c']<jupyter_output><empty_output><jupyter_text>用切片可以对Series的相应部分进行设置：<jupyter_code>obj['b':'c'] = 5
obj<jupyter_output><empty_output><jupyter_text>用一个值或序列对DataFrame进行索引其实就是获取一个或多个列：<jupyter_code>data = pd.DataFrame(np.arange(16).reshape((4, 4)),
                    index=['Ohio', 'Colorado', 'Utah', 'New York'],
                    columns=['one', 'two', 'three', 'four'])
data
data['two']
data[['three', 'one']]<jupyter_output><empty_output><jupyter_text>这种索引方式有几个特殊的情况。首先通过切片或布尔型数组选取数据：<jupyter_code>data[:2]
data[data['three'] > 5]<jupyter_output><empty_output><jupyter_text>选取行的语法data[:2]十分方便。向[ ]传递单一的元素或列表，就可选择列。另一种用法是通过布尔型DataFrame（比如下面这个由标量比较运算得出的）进行索引：<jupyter_code>data < 5
data[data < 5] = 0
data<jupyter_output><empty_output><jupyter_text>Selection with loc and iloc 用loc和iloc进行选取 对于DataFrame的行的标签索引，我引入了特殊的标签运算符loc和iloc。它们可以让你用类似NumPy的标记，使用轴标签（loc）或整数索引（iloc），从DataFrame选择行和列的子集。作为一个初步示例，让我们通过标签选择一行和多列：<jupyter_code>data.loc['Colorado', ['two', 'three']]<jupyter_output><empty_output><jupyter_text>然后用iloc和整数进行选取：<jupyter_code>data
data.iloc[2, [3, 0, 1]]
data.iloc[2]
data.iloc[[1, 2], [3, 0, 1]]<jupyter_output><empty_output><jupyter_text>这两个索引函数也适用于一个标签或多个标签的切片：<jupyter_code>data.loc[:'Utah', 'two']
data.iloc[:, :3][data.three > 5]<jupyter_output><empty_output><jupyter_text>所以，在pandas中，有多个方法可以选取和重新组合数据。对于DataFrame，表5-4进行了总结。后面会看到，还有更多的方法进行层级化索引。> 笔记：在一开始设计pandas时，我觉得用frame[:, col]选取列过于繁琐（也容易出错），因为列的选择是非常常见的操作。我做了些取舍，将花式索引的功能（标签和整数）放到了ix运算符中。在实践中，这会导致许多边缘情况，数据的轴标签是整数，所以pandas团队决定创造loc和iloc运算符分别处理严格基于标签和整数的索引。ix运算符仍然可用，但并不推荐。| 类型                     | 说明                                                         || :------------------------ | :----------------------------------------------------------- || df[val]                  | 从DataFrame选取单列或一组列；在特殊情况下比较便利：布尔型数组（过滤行）、切片（行切片）、或布尔型DataFrame（根据条件设置值） || df.loc[val]              | 通过标签，选取DataFrame的单个行或一组行                      || df.loc[:, val]            | 通过标签，选取单列或列子集                                   || df.loc[val1, val2]        | 通过标签，同时选取行和列                                     || df.iloc[where]           | 通过整数位置，从DataFrame选取单个行或行子集                  || df.iloc[:, where]         | 通过整数位置，从DataFrame选取单个列或列子集                  || df.iloc[where_i, where_j] | 通过整数位置，同时选取行和列                                 || df.at[label_i, label_j]   | 通过行和列标签，选取单一的标量                               || df.iat[i, j]              | 通过行和列的位置（整数），选取单一的标量                     || reindex                  | 通过标签选取行或列                                           || get_value, set_value     | 通过行和列标签选取单一值                                     |  Integer Indexes ser = pd.Series(np.arange(3.))serser[-1]<jupyter_code>ser = pd.Series(np.arange(3.))
ser
ser2 = pd.Series(np.arange(3.), index=['a', 'b', 'c'])
ser2[-1]
ser[:1]
ser.loc[:1]
ser.iloc[:1]<jupyter_output><empty_output><jupyter_text>Arithmetic and Data Alignment 算术运算和数据对齐 pandas最重要的一个功能是，它可以对不同索引的对象进行算术运算。在将对象相加时，如果存在不同的索引对，则结果的索引就是该索引对的并集。对于有数据库经验的用户，这就像在索引标签上进行自动外连接。看一个简单的例子：<jupyter_code>s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
s1
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],
               index=['a', 'c', 'e', 'f', 'g'])
s2<jupyter_output><empty_output><jupyter_text>将它们相加就会产生：<jupyter_code>s1 + s2<jupyter_output><empty_output><jupyter_text>自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。对于DataFrame，对齐操作会同时发生在行和列上：|<jupyter_code>df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'),
                   index=['Ohio', 'Texas', 'Colorado'])
df1
df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
                   index=['Utah', 'Ohio', 'Texas', 'Oregon'])
df2<jupyter_output><empty_output><jupyter_text>把它们相加后将会返回一个新的DataFrame，其索引和列为原来那两个DataFrame的并集：<jupyter_code>df1 + df2<jupyter_output><empty_output><jupyter_text>因为'c'和'e'列均不在两个DataFrame对象中，在结果中以缺省值呈现。行也是同样。如果DataFrame对象相加，没有共用的列或行标签，结果都会是空：<jupyter_code>df1 = pd.DataFrame({'A': [1, 2]})
df1
df2 = pd.DataFrame({'B': [3, 4]})
df2
df1 + df2<jupyter_output><empty_output><jupyter_text>Arithmetic methods with fill values 在算术方法中填充值 在对不同索引的对象进行算术运算时，你可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值（比如0）：<jupyter_code>df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)),
                   columns=list('abcd'))
df2
df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)),
                   columns=list('abcde'))
df2.loc[1, 'b'] = np.nan
df2<jupyter_output><empty_output><jupyter_text>将它们相加时，没有重叠的位置就会产生NA值：<jupyter_code>df1 + df2<jupyter_output><empty_output><jupyter_text>使用df1的add方法，传入df2以及一个fill_value参数：<jupyter_code>df1.add(df2, fill_value=0)
1 / df1
df1.rdiv(1)
df1.reindex(columns=df2.columns, fill_value=0)<jupyter_output><empty_output><jupyter_text>Operations between DataFrame and Series DataFrame和Series之间的运算<jupyter_code>arr = np.arange(12.).reshape((3, 4))
arr
arr[0]
arr - arr[0]
frame = pd.DataFrame(np.arange(12.).reshape((4, 3)),
                     columns=list('bde'),
                     index=['Utah', 'Ohio', 'Texas', 'Oregon'])
series = frame.iloc[0]
frame
series
frame - series
series2 = pd.Series(range(3), index=['b', 'e', 'f'])
frame + series2
series3 = frame['d']
frame
series3
frame.sub(series3, axis='index')<jupyter_output><empty_output><jupyter_text>Function Application and Mapping<jupyter_code>frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
                     index=['Utah', 'Ohio', 'Texas', 'Oregon'])
frame
np.abs(frame)
f = lambda x: x.max() - x.min()
frame.apply(f)
frame.apply(f, axis='columns')
def f(x):
    return pd.Series([x.min(), x.max()], index=['min', 'max'])
frame.apply(f)
format = lambda x: '%.2f' % x
frame.applymap(format)
frame['e'].map(format)<jupyter_output><empty_output><jupyter_text>Sorting and Ranking<jupyter_code>obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
obj.sort_index()
frame = pd.DataFrame(np.arange(8).reshape((2, 4)),
                     index=['three', 'one'],
                     columns=['d', 'a', 'b', 'c'])
frame.sort_index()
frame.sort_index(axis=1)
frame.sort_index(axis=1, ascending=False)
obj = pd.Series([4, 7, -3, 2])
obj.sort_values()
obj = pd.Series([4, np.nan, 7, np.nan, -3, 2])
obj.sort_values()
frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
frame
frame.sort_values(by='b')
frame.sort_values(by=['a', 'b'])
obj = pd.Series([7, -5, 7, 4, 2, 0, 4])
obj.rank()
obj.rank(method='first')
# Assign tie values the maximum rank in the group
obj.rank(ascending=False, method='max')
frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],
                      'c': [-2, 5, 8, -2.5]})
frame
frame.rank(axis='columns')<jupyter_output><empty_output><jupyter_text>Axis Indexes with Duplicate Labels<jupyter_code>obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
obj
obj.index.is_unique
obj['a']
obj['c']
df = pd.DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])
df
df.loc['b']<jupyter_output><empty_output><jupyter_text>Summarizing and Computing Descriptive Statistics<jupyter_code>df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
                   [np.nan, np.nan], [0.75, -1.3]],
                  index=['a', 'b', 'c', 'd'],
                  columns=['one', 'two'])
df
df.sum()
df.sum(axis='columns')
df.mean(axis='columns', skipna=False)
df.idxmax()
df.cumsum()
df.describe()
obj = pd.Series(['a', 'a', 'b', 'c'] * 4)
obj.describe()<jupyter_output><empty_output><jupyter_text>Correlation and Covariance conda install pandas-datareader<jupyter_code>price = pd.read_pickle('examples/yahoo_price.pkl')
volume = pd.read_pickle('examples/yahoo_volume.pkl')<jupyter_output><empty_output><jupyter_text>import pandas_datareader.data as weball_data = {ticker: web.get_data_yahoo(ticker)            for ticker in ['AAPL', 'IBM', 'MSFT', 'GOOG']}price = pd.DataFrame({ticker: data['Adj Close']                     for ticker, data in all_data.items()})volume = pd.DataFrame({ticker: data['Volume']                      for ticker, data in all_data.items()})<jupyter_code>returns = price.pct_change()
returns.tail()
returns['MSFT'].corr(returns['IBM'])
returns['MSFT'].cov(returns['IBM'])
returns.MSFT.corr(returns.IBM)
returns.corr()
returns.cov()
returns.corrwith(returns.IBM)
returns.corrwith(volume)<jupyter_output><empty_output><jupyter_text>Unique Values, Value Counts, and Membership<jupyter_code>obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
uniques = obj.unique()
uniques
obj.value_counts()
pd.value_counts(obj.values, sort=False)
obj
mask = obj.isin(['b', 'c'])
mask
obj[mask]
to_match = pd.Series(['c', 'a', 'b', 'b', 'c', 'a'])
unique_vals = pd.Series(['c', 'b', 'a'])
pd.Index(unique_vals).get_indexer(to_match)
data = pd.DataFrame({'Qu1': [1, 3, 4, 3, 4],
                     'Qu2': [2, 3, 1, 2, 3],
                     'Qu3': [1, 5, 2, 4, 4]})
data
result = data.apply(pd.value_counts).fillna(0)
result<jupyter_output><empty_output><jupyter_text>Conclusion<jupyter_code>pd.options.display.max_rows = PREVIOUS_MAX_ROWS<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16653973089616653, 'fraction_numerical': 0.02553947702462554, 'mean_word_length': 6.847011952191235, 'pattern_counts': {'":': 0, '<': 307, '<?xml version=': 0, '>': 313, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '76', 'dir': 'jupyter-structured-clean-dedup', 'id': '138777', 'license': 'MIT', 'n_tokens_mistral': 10419, 'n_tokens_neox': 10725, 'n_words': 876, 'path': 'ch05.ipynb', 'repo_name': 'wangenyong/pydata-book', 'size': '19695'}