• 第五篇 pandas⼊⻔


    pandas含有使数据清洗和分析⼯作变得更快更简单的数据结构和操作⼯具。
    pandas经常和其它⼯具⼀同使⽤,如数值计算⼯具NumPy和SciPy,分析库statsmodels和scikit-learn,和数据可视化库matplotlib。pandas是基于NumPy数组构建的,特别是基于数组的函数和不使⽤for循环的数据处理。

    pandas与NumPy的不同:pandas采⽤了⼤量的NumPy编码⻛格,不同是pandas是专⻔为处理表格和混杂数据设计的。⽽NumPy更适合处理统⼀的数值数组数据。

    从2010年pandas开源以来,pandas逐渐成⻓为⼀个⾮常⼤的库,应⽤于许多真实案例。开发者社区已经有了800个独⽴的贡献者。

    pandas导⼊约定:import pandas as pd
    Series和DataFrame⽤的次数多,可将其引⼊本地命名空间中会更⽅便:
    from pandas import Series, DataFram

    一、pandas的数据结构介绍
    两个主要数据结构:SeriesDataFrame。虽不能解决所有问题,但它们为⼤多数应⽤提供了⼀种可靠的、易于使⽤的基础。

    1、Series
    Series是⼀种类似于⼀维数组的对象,它由⼀组数据(各种NumPy数据类型)以及⼀组与之相关的数据标签(即索引)组成。仅由⼀组数据即可产⽣最简单的Series:
    obj = pd.Series([4, 7, -5, 3])
    obj       # 输出如下:包含元素索引、元素,以及数据类型
    0    4
    1    7
    2    -5
    3    3
    dtype: int64
    Series的字符串表现形式为:索引在左边,值在右边。未指定索引,于是会⾃动创建⼀个0到N-1(N为数据的⻓度)的整数型索引。可通过Series 的values和index属性获取其数组表示形式和索引对象:
    obj.values      # 输出:array([ 4, 7, -5, 3], dtype=int64)
    obj.index       # 输出:RangeIndex(start=0, stop=4, step=1),(like range(4))

    通常,希望所创建的Series带有⼀个可以对各个数据点进⾏标记的索引:
    obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])  # 指定行索引
    obj2   # 输出如下:
    d    4
    b    7
    a    -5
    c    3
    dtype: int64
    obj2.index # 输出:Index(['d', 'b', 'a', 'c'], dtype='object')
    与普通NumPy数组相⽐,你可以通过索引的⽅式选取Series中的单个或⼀组值:
    obj2['a']      # 输出:-5
    obj2['d'] = 6     # 设定索引'd'的值
    obj2[['c', 'a', 'd']]    # 输出:(注意参数是列表)
    c    3
    a    -5
    d    6
    dtype: int64
    ['c', 'a', 'd']是索引列表,即使它包含的是字符串⽽不是整数。

    使⽤NumPy函数或类似NumPy的运算(如根据布尔型数组进⾏过滤、标量乘法、应⽤数学函数等)都会保留索引值的链接:
    obj2[obj2 > 0]     # 输出:(布尔运算)
    d    6
    b    7
    c    3
    dtype: int64
    obj2 * 2        # 输出:(标量乘法)
    d    12
    b    14
    a    -10
    c    6
    dtype: int64
    np.exp(obj2)     # 输出:(运用于数学函数)
    d    403.428793
    b    1096.633158
    a    0.006738
    c    20.085537
    dtype: float64

    还可以将Series看成是⼀个定⻓的有序字典,因为它是索引值到数据值的⼀个映射。它可以⽤在许多原本需要字典参数的函数中:
    'b' in obj2    # 输出:True
    'e' in obj2    # 输出:False

    如果数据被存放在⼀个Python字典中,也可以直接通过这个字典来创建Series
    sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
    obj3 = pd.Series(sdata)
    obj3        # 输出:
    Ohio    35000
    Texas   71000
    Oregon  16000
    Utah    5000
    dtype: int64
    如果只传⼊⼀个字典,则结果Series中的索引就是原字典的键(有序排列)。你可以传⼊排好序的字典的键以改变顺序:
    states = ['California', 'Ohio', 'Oregon', 'Texas']
    obj4 = pd.Series(sdata, index=states)
    obj4        # 输出:
    California    NaN
    Ohio      35000.0
    Oregon      16000.0
    Texas      71000.0
    dtype: float64
    在这个例⼦中,sdata中跟states索引相匹配的那3个值会被找出来并放到相应的位置上,但由于"California"所对应的sdata值找不到,所以其结果就为NaN(即“⾮数字”(not a number),在pandas中,它⽤于表示缺失或NA值)。因为‘Utah’不在states中,它被从结果中除去。

    使⽤缺失(missing)或NA表示缺失数据。pandas的isnullnotnull函数可⽤于检测缺失数据:
    pd.isnull(obj4)      # 检测obj4中哪些数据缺失
    California    True
    Ohio      False
    Oregon       False
    Texas       False
    dtype: bool
    pd.notnull(obj4)     # 检测obj4中哪些数据不缺失
    California    False
    Ohio      True
    Oregon       True
    Texas     True
    dtype: bool
    Series也有类似的实例⽅法:
    obj4.isnull()       # 检测obj4中哪些数据缺失,obj4.notnull()方法检测数据不缺失
    California    True
    Ohio      False
    Oregon       False
    Texas       False
    dtype: bool

    对于许多应⽤⽽⾔,Series最重要的⼀个功能是,它会根据运算的索引标签⾃动对⻬数据
    obj3      # 输出:
    Ohio      35000
    Texas     71000
    Oregon       16000
    Utah      5000
    dtype: int64
    obj4      # 输出:
    California    NaN
    Ohio      35000.0
    Oregon      16000.0
    Texas         71000.0
    dtype: float64
    obj3 + obj4     # 输出:
    California    NaN
    Ohio      70000.0
    Oregon       32000.0
    Texas      142000.0
    Utah      NaN
    dtype: float64
    该功能类似于数据库的join的操作

    Series对象本身及其索引都有⼀个name属性,该属性跟pandas其他的关键功能关系⾮常密切:
    obj4.name = 'population'     # 设置Series对象本身的name属性
    obj4.index.name = 'state'     # 设置Series对象索引的name属性
    obj4      # 输出如下:
    state
    California    NaN
    Ohio      35000.0
    Oregon      16000.0
    Texas       71000.0
    Name: population, dtype: float64

    Series的索引可以通过赋值的⽅式就地修改:
    obj     # obj的原始索引及数据
    0    4
    1    7
    2    -5
    3    3
    dtype: int64
    obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']   # 修改obj的索引
    obj     # obj修改后的索引及数据,输出如下所示:
    Bob       4
    Steve    7
    Jeff      -5
    Ryan    3
    dtype: int64

    2、DataFrame

    DataFrame是⼀个表格型的数据结构,它含有⼀组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有⾏索引也有列索引,它可以被看做由Series组成的字典(共⽤同⼀个索引)。DataFrame中的数据是以⼀个或多个⼆维块存放的(⽽不是列表、字典或别的⼀维数据结构)。

    虽然DataFrame是以⼆维结构保存数据的,仍可以将其表示为更⾼维度的数据(层次化索引的表格型结构,这是pandas中许多⾼级数据处理功能的关键要素)。

    创建DataFrame的办法很多,最常⽤的⼀种是直接传⼊⼀个由等⻓列表或NumPy数组组成的字典
    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)
    结果DataFrame会⾃动加上索引(跟Series⼀样),且全部列会被有序排列:
    frame      # 输出如下:
          state          year    pop
    0    Ohio         2000    1.5
    1    Ohio         2001    1.7
    2    Ohio      2002    3.6
    3    Nevada    2001    2.4
    4    Nevada    2002    2.9
    5    Nevada    2003    3.2
    使⽤Jupyter notebook,pandas DataFrame对象会以对浏览器友好的HTML表格的⽅式呈现。
    对于特别⼤的DataFrame,head⽅法会选取前五⾏:
    frame.head()     # 输出如下:
        state     year    pop
    0    Ohio    2000    1.5
    1    Ohio    2001    1.7
    2    Ohio    2002    3.6
    3    Nevada    2001    2.4
    4    Nevada    2002    2.9
    如果指定了列序列,则DataFrame的列就会按照指定顺序进⾏排列:
    pd.DataFrame(data, columns=['year', 'state', 'pop'])
         year    state    pop
    0    2000    Ohio    1.5
    1    2001    Ohio    1.7
    2    2002    Ohio    3.6
    3    2001    Nevada     2.4
    4    2002    Nevada     2.9
    5    2003    Nevada     3.2
    如果传⼊的列在数据中找不到,就会在结果中产⽣缺失值:
    frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
                index=['one', 'two', 'three', 'four','five', 'six'])
    frame2      # 输出如下:
          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
    frame2.columns     # 输出: Index(['year', 'state', 'pop', 'debt'], dtype='object')
    通过类似字典标记的⽅式或属性的⽅式,可以将DataFrame的列获取为⼀个Series:
    frame2['state']     # 通过字典的方式获取列
    one    Ohio
    two    Ohio
    three     Ohio
    four    Nevada
    five     Nevada
    six      Nevada
    Name: state, dtype: object

    frame2.year     # 通过属性的方式获取
    one    2000
    two    2001
    three    2002
    four    2001
    five    2002
    six     2003
    Name: year, dtype: int64
    注意:IPython提供了类似属性的访问(即frame2.year)和tab补全。frame2[column]适⽤于任何列的名,但是frame2.column只有在列名是⼀个合理的Python变量名时才适⽤。返回的Series拥有原DataFrame相同的索引,且其name属性也已经被相应地设置好了。

    ⾏也可以通过位置或名称的⽅式进⾏获取,⽐如⽤loc属性
    frame2.loc['three']   # 输出如下:
    year    2002
    state    Ohio
    pop     3.6
    debt    NaN
    Name: three, dtype: object

    列可以通过赋值的⽅式进⾏修改。例如,可以给那个空的"debt"列赋上⼀个标量值或⼀组值:
    frame2['debt'] = 16.5     # 赋值一个标量值
    frame2        # 输出如下:
          year    state    pop    debt
    one    2000    Ohio    1.5    16.5
    two    2001    Ohio     1.7    16.5
    three     2002    Ohio    3.6    16.5
    four    2001    Nevada     2.4    16.5
    five    2002    Nevada      2.9    16.5
    six     2003    Nevada      3.2    16.5
    frame2['debt'] = np.arange(6.)   # 赋值一组值
    frame2        # 输出如下:
          year    state    pop    debt
    one    2000    Ohio    1.5    0.0
    two    2001    Ohio    1.7    1.0
    three    2002    Ohio    3.6    2.0
    four    2001    Nevada    2.4    3.0
    five    2002    Nevada     2.9    4.0
    six     2003    Nevada     3.2    5.0

    将列表或数组赋值给某个列时,其⻓度必须跟DataFrame的⻓度相匹配。如果赋值的是⼀个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值:例如:
    val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
    frame2['debt'] = val      # 精确匹配索引
    frame2       # 输出如下:
          year    state   pop    debt
    one    2000    Ohio    1.5    NaN
    two    2001    Ohio    1.7    -1.2
    three    2002    Ohio    3.6    NaN
    four      2001    Nevada     2.4   1.5
    five    2002    Nevada     2.9    -1.7
    six     2003    Nevada     3.2    NaN

    为不存在的列赋值会创建出⼀个新列。关键字del⽤于删除列。作为del的例⼦,我先添加⼀个新的布尔值的列,判断state是否为'Ohio':
    frame2['eastern'] = frame2.state == 'Ohio'
    frame2        # 输出如下:
          year    state   pop    debt    eastern
    one    2000    Ohio    1.5    NaN    True
    two    2001    Ohio    1.7    -1.2      True
    three    2002    Ohio    3.6    NaN    True
    four   2001    Nevada     2.4  -1.5       False
    five    2002    Nevada     2.9    -1.7    False
    six     2003    Nevada     3.2    NaN    False
    注意:不能⽤frame2.eastern创建新的列。
    del⽅法可以⽤来删除这列:
    del frame2['eastern']
    frame2.columns     # 输出:Index(['year', 'state', 'pop', 'debt'], dtype='object')
    注意:通过索引⽅式返回的列只是相应数据的视图⽽已,并不是副本。因此,对返回的Series所做的任何就地修改全都会反映到源DataFrame上。通过Series的copy⽅法即可指定复制列。

    另⼀种常⻅的数据形式是嵌套字典
    pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
    如果嵌套字典传给DataFrame,pandas就会被解释为:外层字典的键作为列索引,内层键则作为⾏索引:
    frame3 = pd.DataFrame(pop)   # 将字典pop转换为DataFrame
    frame3        # 输出:
        Nevada   Ohio
    2000    NaN    1.5
    2001    2.4      1.7
    2002    2.9      3.6
    也可以使⽤类似NumPy数组的⽅法,对DataFrame进⾏转置(交换⾏和列):
    frame3.T
          2000    2001    2002
    Nevada    NaN    2.4    2.9
    Ohio      1.5    1.7    3.6
    内层字典的键会被合并、排序以形成最终的索引。如果明确指定了索引,则不会这样:
    pd.DataFrame(pop, index=[2001, 2002, 2003])   # 要报错:AttributeError: 'list' object has no attribute 'astype'
    frame55 = pd.DataFrame(pop)        # 先将pop数据转换为DataFrame数据后可指定索引
    pd.DataFrame(frame55, index=[2001, 2002, 2003])   # 这样指定索引排序不会报错
        Nevada   Ohio
    2001    2.4    1.7
    2002    2.9    3.6
    2003    NaN    NaN

    由Series组成的字典差不多也是⼀样的⽤法:
    pdata = {'Ohio': frame3['Ohio'][:-1], 'Nevada': frame3['Nevada'][:2]}   # 注意:依次是列标签,行标签
    pd.DataFrame(pdata)   # 输出如下:(这里使用:pd.DataFrame(pdata, index=[2001,2000]),不会报错)
        Ohio    Nevada
    2000    1.5    NaN
    2001    1.7    2.4

    下面列出了DataFrame构造函数所能接受的各种数据(表5-1):

    如果设置了DataFrame的index和columns的name属性,则这些信息也会被显示出来:
    frame3.index.name = 'year'; frame3.columns.name = 'state'
    frame3    # 输出如下:
    state    Nevada   Ohio
    year
    2000    NaN    1.5
    2001    2.4      1.7
    2002    2.9      3.6

    跟Series⼀样,values属性也会以⼆维ndarray的形式返回DataFrame中的数据:
    frame3.values     # 输出如下:
    array([[nan, 1.5],
       [2.4, 1.7],
          [2.9, 3.6]])

    如果DataFrame各列的数据类型不同,则值数组的dtype就会选⽤能兼容所有列的数据类型:
    frame2.values     # 输出如下:
    array([[2000, 'Ohio', 1.5, nan],
      [2001, 'Ohio', 1.7, -1.2],
      [2002, 'Ohio', 3.6, nan],
      [2001, 'Nevada', 2.4, -1.5],
      [2002, 'Nevada', 2.9, -1.7],
      [2003, 'Nevada', 3.2, nan]], dtype=object)

    1、索引对象
    pandas的索引对象负责管理轴标签和其他元数据(⽐如轴名称等)。构建Series或DataFrame时,所⽤到的任何数组或其他序列的标签都会被转换成⼀个Index:
    obj = pd.Series(range(3), index=['a', 'b', 'c'])
    index = obj.index     # 将obj的索引赋值给另一个变量
    index       # 输出:Index(['a', 'b', 'c'], dtype='object')
    index[1:]         # 输出:Index(['b', 'c'], dtype='object')

    Index对象是不可变的,因此⽤户不能对其进⾏修改:
    index[1] = 'd'   # 提示错误:TypeError: Index does not support mutable operations
    不可变可以使Index对象在多个数据结构之间安全共享:
    labels = pd.Index(np.arange(3))    # 创建一个索引
    labels      # 输出:Int64Index([0, 1, 2], dtype='int64')
    obj2 = pd.Series([1.5, -2.5, 0], index=labels)   # 创建对象时指定索引
    obj2      # 输出可以看出索引是创建时指定的索引
    0    1.5
    1    -2.5
    2    0.0
    dtype: float64
    obj2.index is labels   # 输出:True(验证是否是同一个索引)
    虽然Index功能不经常使用,但一些操作会生成包含索引化的数据,理解它的工作原理很重要。

    除了类似于数组,Index的功能也类似⼀个固定⼤⼩的集合:
    frame3    # 先看下面前的frame3的输出:
    state    Nevada   Ohio
    year
    2000    NaN    1.5
    2001    2.4       1.7
    2002    2.9       3.6
    'Ohio' in frame3.columns   # 输出:True(判断是否在列索引)
    2003 in frame3.index        # 输出:False(判断是否在行索引)

    与python的集合不同,pandas的Index可以包含重复的标签:
    dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])   # 包含重复索引
    dup_labels   # 输出:Index(['foo', 'foo', 'bar', 'bar'], dtype='object')
    选择重复的标签,会显示所有的结果。
    每个索引都有⼀些⽅法和属性,它们可⽤于设置逻辑并回答有关该索引所包含的数据的常⻅问题。下面列出了Index的方法和属性(表5-2)

     

    二、基本功能
    下面介绍操作Series和DataFrame中的数据的基本⼿段。


    1、重新索引(reindex)
    pandas对象的⼀个重要⽅法是reindex,其作⽤是创建⼀个新对象,它的数据符合新的索引。例:
    obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b','a', 'c'])
    obj   # 输出:
    d    4.5
    b    7.2
    a    -5.3
    c    3.6
    dtype: float64
    ⽤该Series的reindex将会根据新索引进⾏重排。如果某个索引值当前不存在,就引⼊缺失值:
    obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])   # 重建索引
    obj2     # 输出:
    a    -5.3
    b    7.2
    c    3.6
    d    4.5
    e    NaN
    dtype: float64

    对于时间序列这样的有序数据,重新索引时可能需要做⼀些插值处理。method选项即可达到此⽬的,例如,使⽤ffill可以实现前向值填充:
    obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
    obj3      # 输出:
    0    blue
    2    purple
    4    yellow
    dtype: object
    obj3.reindex(range(6), method='ffill')   # 输出如下
    0    blue
    1    blue
    2    purple
    3    purple
    4    yellow
    5    yellow
    dtype: object
    借助DataFrame,reindex可以修改(⾏和列)索引。只传递⼀个序列时,会重新索引结果的⾏:
    frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
              index=['a', 'c', 'd'],
              columns=['Ohio', 'Texas', 'California'])
    frame    # 输出:
      Ohio    Texas   California
    a    0    1    2
    c    3    4    5
    d    6    7    8
    frame2 = frame.reindex(['a', 'b', 'c', 'd'])   # 只传递一个序列,修改行索引
    frame2      # 输出
         Ohio      Texas     California
    a    0.0    1.0    2.0
    b    NaN     NaN    NaN
    c    3.0    4.0    5.0
    d   6.0    7.0     8.0
    列可以⽤columns关键字重新索引

    states = ['Texas', 'Utah', 'California']
    frame.reindex(columns=states)    # 指定columns关键字,修改列索引
      Texas   Utah     California
    a    1    NaN    2
    c    4    NaN    5
    d    7    NaN    8

    下面列出了reindex函数的各参数及说明(表5-3)

    2、丢弃指定轴上的项
    丢弃某条轴上的⼀个或多个项很简单,只要有⼀个索引数组或列表即可。由于需要执⾏⼀些数据整理和集合逻辑,所以drop⽅法返回的是⼀个在指定轴上删除了指定值的新对象:
    obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])   # 假设有这个Series序列
    obj      # 输出如下
    a    0.0
    b    1.0
    c    2.0
    d    3.0
    e    4.0
    dtype: float64
    new_obj = obj.drop('c')   # 删除传入的值,并得到新的Index
    new_obj
    a    0.0
    b    1.0
    d    3.0
    e    4.0
    dtype: float64
    obj.drop(['d', 'c'])      # 删除传入的值,注意参数是列表
    a    0.0
    b    1.0
    e    4.0
    dtype: float64

    对于DataFrame,可以删除任意轴上的索引值。先新建⼀个DataFrame例⼦:
    data = pd.DataFrame(np.arange(16).reshape((4, 4)),
              index=['Ohio', 'Colorado', 'Utah', 'New York'],
              columns=['one', 'two', 'three', 'four'])
    data    # 输出如下:
        one   two    three     four
    Ohio    0    1   2    3
    Colorado  4    5   6    7
    Utah    8    9    10    11
    New York 12   13    14    15
    标签序列调⽤drop会从⾏标签(axis 0)删除值:
    data.drop(['Colorado', 'Ohio'])    # 输出如下:
        one   two   three   four
    Utah    8    9    10    11
    New York 12   13    14    15
    通过传递axis=1或axis='columns'可以删除列的值:
    data.drop('two', axis=1)    # 输出如下:
        one  three    four
    Ohio    0    2      3
    Colorado  4    6      7
    Utah    8   10    11
    New York 12    14    15
    data.drop(['two', 'four'], axis='columns')   # 输出如下:
        one     three
    Ohio    0    2
    Colorado  4    6
    Utah    8    10
    New York 12   14

    许多函数,如drop,会修改Series或DataFrame的⼤⼩或形状,可就地修改对象,不会返回新的对象:
    obj.drop('c', inplace=True)   # ⼩⼼使⽤inplace,它会销毁所有被删除的数据。
    obj    # 输出如下:
    a    0.0
    b    1.0
    d    3.0
    e    4.0
    dtype: float64

    3、索引、选取和过滤
    Series索引(obj[...])的⼯作⽅式类似于NumPy数组的索引,只不过Series的索引值不只是整数。例如:
    obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
    obj   # 输出如下:
    a    0.0
    b    1.0
    c    2.0
    d    3.0
    dtype: float64
    obj['b']      # 输出:1.0
    obj[1]       # 输出:1.0
    obj[2:4]    # 输出如下:
    c    2.0
    d    3.0
    dtype: float64
    obj[['b', 'a', 'd']]   # 输出如下:
    b    1.0
    a    0.0
    d    3.0
    dtype: float64
    obj[[1, 3]]      # 输出如下:(参数是列表)
    b    1.0
    d    3.0
    dtype: float64
    obj[obj < 2]    # 输出如下:(按条件索引,布尔索引)
    a    0.0
    b    1.0
    dtype: float64
    利⽤标签的切⽚运算与普通的Python切⽚运算不同,其末端是包含的:
    obj['b':'c']    # 输出如下:
    b   1.0
    c    2.0
    dtype: float64
    ⽤切⽚可以对Series的相应部分进⾏设置
    obj['b':'c'] = 5
    obj    # 输出如下:
    a    0.0
    b    5.0
    c    5.0
    d    3.0
    dtype: float64

    ⽤⼀个值或序列对DataFrame进⾏索引其实就是获取⼀个或多个列
    data = pd.DataFrame(np.arange(16).reshape((4, 4)),
              index=['Ohio', 'Colorado', 'Utah', 'New York'],
              columns=['one', 'two', 'three', 'four'])
    data    # 输出如下:
        one   two  three     four
    Ohio    0    1      2   3
    Colorado  4    5      6    7
    Utah    8    9    10    11
    New York 12   13    14    15
    data['two']   # 输出如下
    Ohio    1
    Colorado  5
    Utah    9
    New York 13
    Name: two, dtype: int32
    data[['three', 'one']]   # 输出如下:
        three   one
    Ohio      2    0
    Colorado    6    4
    Utah    10    8
    New York 14    12
    data[:2]    # 输出如下:(选取前2行)
        one   two   three    four
    Ohio    0    1    2    3
    Colorado  4    5    6    7
    data[data['three'] > 5]   # 输出如下:(选取满足条件的行)
        one   two    three       four
    Colorado  4    5    6      7
    Utah    8    9   10    11
    New York 12    13   14    15
    选取⾏的语法data[:2]⼗分⽅便。向[ ]传递单⼀的元素或列表,就可选择列

    另⼀种⽤法是通过布尔型DataFrame进⾏索引:⽐如下⾯这个由标量⽐较运算得出的
    data < 5    # 输出如下:
            one     two     three      four
    Ohio    True      True      True     True
    Colorado  True      False    False    False
    Utah    False    False    False    False
    New York False    False    False    False
    data[data < 5] = 0   # 输出如下:(改变满足条件的值)
    data
        one   two    three       four
    Ohio    0    0   0        0
    Colorado  0    5    6       7
    Utah    8    9    10    11
    New York 12   13    14    15
    这使得DataFrame的语法与NumPy⼆维数组的语法很像。

    4、⽤loc和iloc进⾏选取

    DataFrame⾏标签索引,引⼊特殊的标签运算符loc和iloc。它们可以像⽤类似NumPy的标记,使⽤轴标签(loc)或整数索引(iloc),从DataFrame选择⾏和列的⼦集。先看⼀个初步示例,通过标签选择⼀⾏和多列:
    data.loc['Colorado', ['two', 'three']]   # 选取'Colorado'行,和 ['two', 'three']列,输出如下:
    two      5
    three    6
    Name: Colorado, dtype: int32
    然后⽤iloc和整数进⾏选取:
    data.iloc[2, [3, 0, 1]]    # 输出如下:
    four    11
    one    8
    two    9
    Name: Utah, dtype: int32
    data.iloc[2]   # 输出如下:(选取第三行数据)
    one    8
    two    9
    three   10
    four    11
    Name: Utah, dtype: int32
    data.iloc[[1, 2], [3, 0, 1]]   # 输出如下:(选取多行和多列)
          four    one    two
    Colorado      7    0    5
    Utah      11    8    9

    这两个索引函数也适⽤于⼀个标签或多个标签的切⽚:
    data.loc[:'Utah', 'two']     # 输出如下:
    Ohio    0
    Colorado  5
    Utah    9
    Name: two, dtype: int32
    data.iloc[:, :3][data.three > 5]   # 输出如下:(选取满足多种条件的数据)
          one    two    three
    Colorado      0    5    6
    Utah         8    9    10
    New York    12    13    14
    在pandas中,有多个⽅法可以选取和重新组合数据。当然还有更多的方法进行层级化索引。

    DataFrame的索引选项如下所示(表5-4):

    5、整数索引
    pandas整数索引与Python内置的列表和元组的索引语法不同
    例如,你可能不认为下⾯的代码会出错:
    ser = pd.Series(np.arange(3.))
    ser   # 输出如下:
    0   0.0
    1   1.0
    2   2.0
    dtype: float64
    ser[-1]   # 索引会报错,KeyError: -1,因为轴索引含有整数
    ser有包含0,1,2的索引,但是引⼊⽤户想要的东⻄(基于标签或位置的索引)很难:

    另外,对于⾮整数索引,不会产⽣歧义:
    ser2 = pd.Series(np.arange(3.), index=['a', 'b', 'c'])
    ser2[-1]    # 输出:2.0
    为了进⾏统⼀,如果轴索引含有整数,数据选取总会使⽤标签。为了更准确,请使⽤loc(标签)或iloc(整数)
    ser[:1]   # 整数索引,注意看与下面2个索引的区别,输出如下:
    0    0.0
    dtype: float64
    ser.loc[:1]    # 标签索引,输出如下:
    0    0.0
    1    1.0
    dtype: float64
    ser.iloc[:1]    # 整数索引,输出如下:
    0    0.0
    dtype: float64

    6、算术运算和数据对⻬
    pandas最重要的⼀个功能是,它可以对不同索引的对象进⾏算术运算在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于有数据库经验的话,这就像在索引标签上进⾏⾃动外连接。看⼀个简单的例⼦:
    s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
    s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],
            index=['a', 'c', 'e', 'f', 'g'])
    s1    # 输出如下:
    a    7.3
    c    -2.5
    d    3.4
    e    1.5
    dtype: float64
    s2    # 输出如下:
    a    -2.1
    c    3.6
    e    -1.5
    f    4.0
    g    3.1
    dtype: float64
    s1 + s2    # 输出如下:
    a    5.2
    c    1.1
    d    NaN
    e    0.0
    f    NaN
    g    NaN
    dtype: float64
    ⾃动的数据对⻬操作在不重叠的索引处引⼊了NA值。缺失值会在算术运算过程中传播。

    对于DataFrame,对⻬操作会同时发⽣在⾏和列上:
    df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'), index=['Ohio', 'Texas', 'Colorado'])
    df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
    df1    # 输出如下:
          b     c       d
    Ohio      0.0    1.0    2.0
    Texas    3.0    4.0    5.0
    Colorado    6.0    7.0    8.0
    df2    # 输出如下:
             b       d       e
    Utah         0.0    1.0    2.0
    Ohio         3.0    4.0    5.0
    Texas       6.0    7.0    8.0
    Oregon    9.0    10.0   11.0

    把它们相加后将会返回⼀个新的DataFrame,其索引和列为原来那两个DataFrame的并集:
    df1 + df2    # 输出如下:
            b        c        d      e
    Colorado    NaN    NaN   NaN    NaN
    Ohio      3.0      NaN    6.0     NaN
    Oregon      NaN    NaN    NaN    NaN
    Texas     9.0    NaN    12.0    NaN
    Utah     NaN    NaN    NaN    NaN
    因为'c'和'e'列均不在两个DataFrame对象中,在结果中以缺省值呈现。⾏也是同样。

    如果DataFrame对象相加,没有共⽤的列或⾏标签,结果都会是空
    df1 = pd.DataFrame({'A': [1, 2]})
    df2 = pd.DataFrame({'B': [3, 4]})
    df1    # 输出如下:
          A
    0    1
    1    2
    df2    # 输出如下:
          B
    0    3
    1    4
    df1 - df2    # 输出如下:(没有共⽤的列或⾏标签,结果都会是空)
        A     B
    0   NaN   NaN
    1   NaN   NaN

    7、在算术⽅法中填充值
    在对不同索引的对象进⾏算术运算时,你可能希望当⼀个对象中某个轴标签在另⼀个对象中找不到时填充⼀个特殊值(⽐如0):
    df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd'))
    df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde'))
    df2.loc[1, 'b'] = np.nan
    df1    # 输出如下:
        a       b      c       d
    0    0.0    1.0      2.0    3.0
    1    4.0    5.0      6.0    7.0
    2    8.0    9.0    10.0    11.0
    df2    # 输出如下:
          a       b       c      d       e
    0      0.0    1.0       2.0      3.0    4.0
    1      5.0    NaN    7.0       8.0    9.0
    2    10.0    11.0    12.0    13.0    14.0
    3    15.0    16.0    17.0    18.0    19.0
    将它们相加时,没有重叠的位置就会产⽣NA值:
    df1 + df2    # 输出如下:
        a      b       c      d       e
    0    0.0        2.0    4.0        6.0    NaN
    1    9.0      NaN    13.0    15.0    NaN
    2    18.0    20.0    22.0     24.0    NaN
    3    NaN    NaN    NaN    NaN    NaN
    使⽤df1的add⽅法,传⼊df2以及⼀个fill_value参数
    df1.add(df2, fill_value=0)   # 输出如下:(参数fill_value指定缺失的话用替代)
          a       b          c       d         e
    0      0.0    2.0        4.0    6.0      4.0
    1      9.0    5.0      13.0    15.0    9.0
    2    18.0    20.0    22.0    24.0    14.0
    3    15.0    16.0    17.0    18.0    19.0

    下面列出了Series和DataFrame的算术⽅法。它们每个都有⼀个副本,以字⺟r开头,
    它会翻转参数。因此这两个语句是等价的:
    1 / df1    # 输出如下:
            a        b            c            d
    0        inf  1.000000    0.500000    0.333333
    1    0.250000     0.200000    0.166667    0.142857
    2    0.125000     0.111111      0.100000    0.090909
    df1.rdiv(1)    # 输出如下:
            a        b            c            d
    0        inf  1.000000    0.500000    0.333333
    1    0.250000     0.200000    0.166667    0.142857
    2    0.125000     0.111111      0.100000    0.090909

    灵活的算术⽅法(Series和DataFrame的算术⽅法)(表5-5):

    与此类似,在对Series或DataFrame重新索引时,也可以指定⼀个填充值
    df1.reindex(columns=df2.columns, fill_value=0)     # 输出如下:
        a     b      c       d    e
    0    0.0    1.0    2.0    3.0    0
    1    4.0    5.0    6.0    7.0    0
    2    8.0    9.0     10.0     11.0    0

    8、DataFrame和Series之间的运算

    DataFrame和Series之间算术运算也是有明确规定的。先来看⼀个例⼦,计算⼀个⼆维数组与其某⾏之间的差:
    arr = np.arange(12.).reshape((3, 4))
    arr    # 输出如下:
    array([[ 0., 1., 2., 3.],
      [ 4., 5., 6., 7.],
      [ 8., 9., 10., 11.]])
    arr[0]      # 输出:array([0., 1., 2., 3.])
    arr - arr[0]    # 输出如下:
    array([[0., 0., 0., 0.],
      [4., 4., 4., 4.],
      [8., 8., 8., 8.]])
    当从arr减去arr[0],每⼀⾏都会执⾏这个操作。这就叫做⼴播(broadcasting)。DataFrame和Series之间的运算差不多也是如此:
    frame = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
    series = frame.iloc[0]
    frame   # 输出如下:
          b      d     e
    Utah     0.0    1.0    2.0
    Ohio     3.0    4.0    5.0
    Texas   6.0    7.0    8.0
    Oregon   9.0    10.0   11.0
    series    # 输出如下:
    b    0.0
    d    1.0
    e    2.0
    Name: Utah, dtype: float64
    默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着⾏⼀直向下⼴播:
    frame - series   # 输出如下:
           b       d       e
    Utah    0.0    0.0    0.0
    Ohio    3.0    3.0    3.0
    Texas     6.0    6.0    6.0
    Oregon  9.0    9.0    9.0

    如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集:
    series2 = pd.Series(range(3), index=['b', 'e', 'f'])
    frame + series2   # 输出如下:
          b      d       e       f
    Utah    0.0   NaN    3.0    NaN
    Ohio    3.0   NaN    6.0    NaN
    Texas     6.0   NaN    9.0    NaN
    Oregon  9.0   NaN    12.0   NaN

    如果你希望匹配⾏且在列上⼴播,则必须使⽤算术运算⽅法。例如:
    frame    # 输出如下:
             b       d       e
    Utah    0.0    1.0    2.0
    Ohio    3.0    4.0    5.0
    Texas     6.0    7.0    8.0
    Oregon   9.0   10.0   11.0
    series3    # 输出如下:
    Utah    1.0
    Ohio    4.0
    Texas   7.0
    Oregon  10.0
    Name: d, dtype: float64
    frame.sub(series3, axis='index')    # 输出如下:
             b     d       e
    Utah        -1.0    0.0    1.0
    Ohio        -1.0    0.0    1.0
    Texas      -1.0    0.0    1.0
    Oregon   -1.0    0.0    1.0
    传⼊的轴号就是希望匹配的轴。在本例中,我们的⽬的是匹配DataFrame的⾏索引(axis='index' or axis=0)并进⾏⼴播。

    9、函数应⽤和映射
    NumPy的ufuncs(元素级数组⽅法)也可⽤于操作pandas对象:
    frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
    frame    # 输出如下:
              b        d          e
    Utah    -0.238758   -1.228157   -0.433499
    Ohio    0.281959    0.229944    1.908042
    Texas   -1.180401   -0.234310   -0.264257
    Oregon  0.635323   -1.248893    1.319811
    np.abs(frame)   # 输出如下:
            b        d       e
    Utah    0.238758    1.228157    0.433499
    Ohio    0.281959    0.229944    1.908042
    Texas     1.180401    0.234310    0.264257
    Oregon     0.635323    1.248893    1.319811

    另⼀个常⻅的操作是,将函数应⽤到由各列或⾏所形成的⼀维数组上。DataFrame的apply⽅法即可实现此功能:
    f = lambda x: x.max() - x.min()
    frame.apply(f)   # 输出如下:
    b    1.815723
    d    1.478837
    e    2.341541
    dtype: float64
    这⾥的函数f,计算了⼀个Series的最⼤和虽⼩的差,在frane的每列都执⾏了⼀次。结果是⼀个Series,使⽤frame的列作为索引。

    如果传递axis='columns'到apply,这个函数会在每⾏执⾏:
    frame.apply(f, axis='columns')   # 输出如下:
    Utah    0.989399
    Ohio    1.678098
    Texas   0.946090
    Oregon   2.568704
    dtype: float64
    许多常⻅的数组统计功能都被实现成DataFrame的⽅法(如sum和mean),因此⽆需使⽤apply⽅法。传递到apply的函数不是必须返回⼀个标量,还可以返回由多个值组成的Series:
    def f(x):
      return pd.Series([x.min(), x.max()], index=['min', 'max'])
    frame.apply(f)    # 输出如下:
            b         d         e
    min   -1.180401   -1.248893   -0.433499
    max      0.635323    0.229944    1.908042

    元素级的Python函数也是可以⽤的。假如你想得到frame中各个浮点值的格式化字符串,使⽤applymap即可:
    format = lambda x: '%.2f' % x
    frame.applymap(format)   # 输出如下:
          b      d     e
    Utah    -0.24    -1.23   -0.43
    Ohio    0.28    0.23      1.91
    Texas   -1.18    -0.23    -0.26
    Oregon  0.64    -1.25    1.32
    之所以叫做applymap,是因为Series有⼀个⽤于应⽤元素级函数的map⽅法
    frame['e'].map(format)   # 输出如下:
    Utah    -0.43
    Ohio    1.91
    Texas   -0.26
    Oregon   1.32
    Name: e, dtype: object

    10、排序和排名
    根据条件对数据集排序(sorting)也是⼀种重要的内置运算。要对⾏或列索引进⾏排序(按字典顺序),可使⽤sort_index⽅法,它将返回⼀个已排序的新对象:
    obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
    obj.sort_index()    # 输出如下:
    a    1
    b    2
    c    3
    d    0
    dtype: int64

    对于DataFrame,则可以根据任意⼀个轴上的索引进⾏排序:
    frame = pd.DataFrame(np.arange(8).reshape((2, 4)), index=['three', 'one'], columns=['d', 'a', 'b', 'c'])
    frame.sort_index()    # 输出如下:(行索引排序)
           d    a    b    c
    one      4    5    6    7
    three    0    1   2    3
    frame.sort_index(axis=1)   # 输出如下:(指定参数axis=1按列标签排序)
           a    b    c    d
    three    1    2    3    0
    one      5    6    7    4
    数据默认是按升序排序的,但也可以降序排序:
    frame.sort_index(axis=1, ascending=False)   # 输出如下:(列标签降序排序)
           d    c    b    a
    three    0    3    2   1
    one      4    7   6    5

    若要按值对Series进⾏排序,可使⽤其sort_values⽅法:
    obj = pd.Series([4, 7, -3, 2])
    obj.sort_values()     # 输出如下:
    2    -3
    3    2
    0    4
    1    7
    dtype: int64
    在排序时,任何缺失值默认都会被放到Series的末尾:
    obj = pd.Series([4, np.nan, 7, np.nan, -3, 2])
    obj.sort_values()   # 输出如下:
    4    -3.0
    5    2.0
    0    4.0
    2    7.0
    1    NaN
    3    NaN
    dtype: float64

    当排序⼀个DataFrame时,你可能希望根据⼀个或多个列中的值进⾏排序。将⼀个或多个列的名字传递给sort_values的by选项即可达到该⽬的:
    frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
    frame.sort_values(by='b')   # 输出如下:(对b列排序)
          b    a
    2   -3    0
    3    2    1
    0    4    0
    1    7    1
    要根据多个列进⾏排序,传⼊名称的列表即可:
    frame.sort_values(by=['a', 'b'])   # 输出如下:(参数是列表)
          b    a
    2   -3    0
    0    4    0
    3    2    1
    1    7    1

    排名会从1开始⼀直到数组中有效数据的数量。接下来介绍Series和DataFrame的rank⽅法
    默认情况下,rank是通过“为各组分配⼀个平均排名”的⽅式破坏平级关系的:
    obj = pd.Series([7, -5, 7, 4, 2, 0, 4])
    obj.rank()    # 输出如下:
    0    6.5
    1    1.0
    2    6.5
    3    4.5
    4    3.0
    5    2.0
    6    4.5
    dtype: float64
    也可以根据值在原数据中出现的顺序给出排名:
    obj.rank(method='first')   # 输出如下:
    0    6.0
    1    1.0
    2    7.0
    3    4.0
    4    3.0
    5   2.0
    6   5.0
    dtype: float64
    这⾥,条⽬0和2没有使⽤平均排名6.5,它们被设成了6和7,因为数据中标签0位于标签2的前⾯。
    也可以按降序进⾏排名:
    obj.rank(ascending=False, method='max')   # 输出如下:
    0    2.0
    1    7.0
    2    2.0
    3    4.0
    4    5.0
    5    6.0
    6    4.0
    dtype: float64

    DataFrame可以在⾏或列上计算排名:
    frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1], 'c': [-2, 5, 8, -2.5]})

    frame    # 输出如下:
        b    a       c
    0    4.3    0   -2.0
    1    7.0    1    5.0
    2   -3.0    0    8.0
    3    2.0    1   -2.5
    frame.rank(axis='columns')   # 输出如下:
        b      a     c
    0    3.0    2.0    1.0
    1    3.0    1.0    2.0
    2    1.0    2.0    3.0
    3    3.0    2.0    1.0

    下面是所有⽤于破坏平级关系的method选项(排名时⽤于破坏平级关系的⽅法)(表5-6)

    11、带有重复标签的轴索引
    pandas函数(如reindex)都要求标签唯⼀,但这并不是强制性的。下面是带有重复索引值的Series:
    obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
    obj    # 输出如下:
    a    0
    a    1
    b    2
    b    3
    c    4
    dtype: int64
    索引的is_unique属性可以告诉你它的值是否是唯⼀的:
    obj.index.is_unique   # 输出:False
    对于带有重复值的索引,数据选取的⾏为将会有些不同。如果某个索引对应多个值,则返回⼀个Series;⽽对应单个值的,则返回⼀个标量值:
    obj['a']    # 输出如下:(返回的是Series)
    a    0
    a    1
    dtype: int64
    obj['c']    # 输出: 4(返回的是一个标量)
    这样会使代码变复杂,因为索引的输出类型会根据标签是否有重复发⽣变化。

    对DataFrame的⾏进⾏索引时也是如此:
    df = pd.DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])
    df    # 输出如下:
            0            1       2
    a    1.280512    1.843114   -0.818365
    a    0.919565   -0.214873    0.862256
    b    1.367134    0.730995   -0.427160
    b   -1.763069    0.130508    0.133941
    df.loc['b']      # 输出如下:
            0       1        2
    b    1.367134    0.730995   -0.427160
    b   -1.763069    0.130508    0.133941

    三、汇总和计算描述统计
    pandas对象拥有⼀组常⽤的数学和统计⽅法。⼤部分都属于约简和汇总统计,⽤于从Series中提取单个值(如sum或mean)或从DataFrame的⾏或列中提取⼀个Series。跟对应的NumPy数组⽅法相⽐,它们都是基于没有缺失数据的假设⽽构建的。看⼀个简单的DataFrame:
    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   # 输出如下:
         one     two
    a    1.40    NaN
    b    7.10    -4.5
    c    NaN    NaN
    d    0.75    -1.3
    调⽤DataFrame的sum⽅法将会返回⼀个含有列的和的Series
    df.sum()      # 输出如下:
    one    9.25
    two   -5.80
    dtype: float64
    传⼊axis='columns'或axis=1将会按⾏进⾏求和运算:
    df.sum(axis=1)   # 输出如下:
    a    1.40
    b    2.60
    c    0.00
    d    -0.55
    dtype: float64
    NA值会⾃动被排除,除⾮整个切⽚(这⾥指的是⾏或列)都是NA。通过skipna选项可以禁⽤该功能:
    df.mean(axis='columns', skipna=False)   # 输出如下:(排除有NA值的行)
    a    NaN
    b    1.300
    c    NaN
    d    -0.275
    dtype: float64

    下面列出了约简⽅法的常⽤选项(表5-7):

    有些⽅法(如idxmin和idxmax)返回的是间接统计(⽐如达到最⼩值或最⼤值的索引):
    df.idxmax()   # 输出如下:
    one    b
    two    d
    dtype: object

    另⼀些⽅法则是累计型的:
    df.cumsum()   # 输出如下:(按列累加)
           one      two
    a    1.40    NaN
    b    8.50    -4.5
    c    NaN   NaN
    d    9.25    -5.8
    还有⼀种⽅法,它既不是约简型也不是累计型。describe就是⼀个例⼦,它⽤于⼀次性产⽣多个汇总统计
    df.describe()     # 输出如下:
               one        two
    count    3.000000    2.000000
    mean    3.083333    -2.900000
    std        3.493685    2.262742
    min       0.750000    -4.500000
    25%     1.075000    -3.700000
    50%     1.400000    -2.900000
    75%      4.250000    -2.100000
    max      7.100000    -1.300000
    对于⾮数值型数据,describe会产⽣另外⼀种汇总统计:
    obj = pd.Series(['a', 'a', 'b', 'c'] * 4)   
    obj.describe()    # 输出如下:
    count    16
    unique    3
    top      a
    freq       8
    dtype: object

    下面列出了所有与描述统计相关的⽅法(描述和汇总统计)(表5-8):

    1、相关系数与协⽅差
    有些汇总统计(如相关系数和协⽅差)是通过参数对计算出来的。我们来看⼏个DataFrame,它们的数据来⾃Yahoo!Finance的股票价格和成交量,使⽤的是pandas-datareader包(可以⽤conda或pip安装):
    conda install pandas-datareader

    使⽤pandas_datareader模块下载了⼀些股票数据:
    all_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()})
    注:Yahoo被Verizon收购,上面代码可能运行不成功。目前测试是成功的。参阅pandas-datareader⽂档,可以学习最新的功能。

    returns = price.pct_change()
    returns.tail()     # 输出如下:
              AAPL       IBM      MSFT     GOOG
    Date
    2018-11-23   -0.025399   -0.011639   -0.000388   -0.013232
    2018-11-26    0.013524    0.020224    0.032987    0.024163
    2018-11-27   -0.002176    0.003931    0.006293    -0.004015
    2018-11-28    0.038453    0.024744    0.037148    0.040042
    2018-11-29   -0.007682   -0.012358   -0.008369    0.001906

    Series的corr⽅法⽤于计算两个Series中重叠的、⾮NA的、按索引对⻬的值的相关系数。与此类似,cov⽤于计算协⽅差:
    returns['MSFT'].corr(returns['IBM'])   # 输出:0.4764567156320382
    returns['MSFT'].cov(returns['IBM'])   # 输出:8.31764255718186e-05
    因为MSTF是⼀个合理的Python属性,我们还可以⽤更简洁的语法选择列:
    returns.MSFT.corr(returns.IBM)       # 输出:0.4764567156320382

    DataFrame的corr和cov⽅法将以DataFrame的形式分别返回完整的相关系数或协⽅差矩阵:
    returns.corr()     # 输出如下:
             AAPL       IBM     MSFT      GOOG
    AAPL    1.000000    0.363002    0.429684    0.441674
    IBM       0.363002    1.000000    0.476457    0.398712
    MSFT    0.429684    0.476457    1.000000    0.524992
    GOOG   0.441674    0.398712    0.524992    1.000000
    returns.cov()     # 输出如下:
             AAPL       IBM      MSFT      GOOG
    AAPL    0.000262    0.000071    0.000100    0.000110
    IBM       0.000071    0.000148    0.000083    0.000074
    MSFT    0.000100   0.000083    0.000206    0.000116
    GOOG     0.000110    0.000074    0.000116    0.000235

    利⽤DataFrame的corrwith⽅法,可以计算其列或⾏跟另⼀个Series或DataFrame之间的相关系数。传⼊⼀个Series将会返回⼀个相关系数值Series(针对各列进⾏计算):
    returns.corrwith(returns.IBM)   # 输出如下:
    AAPL    0.363002
    IBM       1.000000
    MSFT    0.476457
    GOOG   0.398712
    dtype: float64

    传⼊⼀个DataFrame则会计算按列名配对的相关系数。这⾥,计算百分⽐变化与成交量的相关系数:
    returns.corrwith(volume)   # 输出如下:
    AAPL    -0.060845
    IBM       -0.177534
    MSFT   -0.087247
    GOOG   -0.016870
    dtype: float64
    传⼊axis='columns'即可按⾏进⾏计算。⽆论如何,在计算相关系数之前,所有的数据项都会按标签对⻬。

    2、唯⼀值、值计数以及成员资格
    还有⼀类⽅法可以从⼀维Series的值中抽取信息。看下⾯的例⼦:
    obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
    uniques = obj.unique()
    uniques    # 输出:array(['c', 'a', 'd', 'b'], dtype=object)
    返回的唯⼀值是未排序的,如果需要的话,可以对结果再次进⾏排序(uniques.sort())。相似的,value_counts⽤于计算⼀个Series中各值出现的频率:
    obj.value_counts() # 输出如下:
    a    3
    c    3
    b    2
    d    1
    dtype: int64
    为了便于查看,结果Series是按值频率降序排列的。value_counts还是⼀个顶级pandas⽅法,可⽤于任何数组或序列:
    pd.value_counts(obj.values, sort=False)   # 输出如下:
    c    3
    a    3
    d    1  
    b    2
    dtype: int64

    isin⽤于判断⽮量化集合的成员资格,可⽤于过滤Series中或DataFrame列中数据的⼦集:
    obj   # 输出如下:
    0    c
    1    a
    2    d
    3    a
    4    a
    5    b
    6    b
    7    c
    8    c
    dtype: object
    mask = obj.isin(['b', 'c'])
    mask    # 输出如下:
    0    True
    1    False
    2    False
    3    False
    4    False
    5    True
    6    True
    7    True
    8    True
    dtype: bool
    obj[mask]    # 输出如下:
    0    c
    5    b
    6    b
    7    c
    8    c
    dtype: object

    与isin类似的是Index.get_indexer⽅法,它可以给你⼀个索引数组,从可能包含重复值的数组到另⼀个不同值的数组:
    to_match = pd.Series(['c', 'a', 'b', 'b', 'c', 'a'])
    unique_vals = pd.Series(['c', 'b', 'a'])
    # 将to_match的索引设置为unique_vals的索引
    pd.Index(unique_vals).get_indexer(to_match)   # 输出:array([0, 2, 1, 1, 0, 2], dtype=int64)

    表5-9 唯⼀值、值计数、成员资格⽅法(这⼏个⽅法的⼀些参考信息)


    有时,可能希望得到DataFrame中多个相关列的⼀张柱状图。例如:
    data = pd.DataFrame({'Qu1': [1, 3, 4, 3, 4], 'Qu2': [2, 3, 1, 2, 3], 'Qu3': [1, 5, 2, 4, 4]})
    将pandas.value_counts传给该DataFrame的apply函数,就会出现:
    result = data.apply(pd.value_counts).fillna(0)
    result    # 输出如下:
         Qu1    Qu2    Qu3
    1    1.0    1.0    1.0
    2    0.0    2.0    1.0
    3    2.0    2.0    0.0
    4    2.0    0.0    2.0
    5    0.0    0.0    1.0
    这⾥,结果中的⾏标签是所有列的唯⼀值。这些值是每个列中这些值的相应计数。

  • 相关阅读:
    牛客寒假6-I 导航系统
    牛客寒假6-C汉诺塔
    P1282 多米诺骨牌【dp】
    VisualStudio中C++程序输出一闪而过的解决方案
    【网络流24题】【LOJ6224】深海机器人问题(最大费用最大流)
    【网络流24题】【LOJ6013】负载平衡(环形纸牌均分,最小费最大流)
    【网络流24题】【LOJ6010】数字梯形(费用流)
    【网络流24题】【LOJ6000】搭配飞行员(二分图最大匹配,最大流Dinic)
    路由器相关
    PC启动原理
  • 原文地址:https://www.cnblogs.com/Micro0623/p/10089908.html
Copyright © 2020-2023  润新知