在加载了,在加载了

【学习笔记】 第05章 pandas入门

前言

上一篇学习中学成的随笔是我的第一篇随笔,撰写中有颇多不足,比如事无巨细的写入学习过程反而像是在抄书,失去了很多可读性也不利于自己反过头来复习,本章节学习需要多加注意,尽量写下较为关键的内容,犯下的错误,难以理解的概念等等
pandas含有使数据清洗和分析工作变得更快更简单的数据结构和操作工具。pandas经常和其它工具一同使用,如数值计算工具NumPy和SciPy,分析库statsmodels和scikit-learn,和数据可视化库matplotlib。pandas是基于NumPy数组构建的,特别是基于数组的函数和不使用for循环的数据处理。
虽然pandas采用了大量的NumPy编码风格,但二者最大的不同是pandas是专门为处理表格和混杂数据设计的。而NumPy更适合处理统一的数值数组数据。

pandas的数据结构介绍

Series和DataFrame

Series

Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。
这里可以通过Series 的values和index属性获取其数组表示形式和索引对象

In [13]: obj.values
Out[13]: array([ 4,  7, -5,  3])

In [14]: obj.index  # like range(4)
Out[14]: RangeIndex(start=0, stop=4, step=1)

如果需要所创建的Series带有一个可以对各个数据点进行标记的索引,则

obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])

即可
与普通NumPy数组相比,你可以通过索引的方式选取Series中的单个或一组值,而使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接
如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series:

In [26]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
In [27]: obj3 = pd.Series(sdata)

而如果传入一个字典,该字典与series值无法一一对应(缺少对应),则该位置结果会变成NaN(非数字)
pandas的isnull和notnull函数可用于检测缺失数据
对于许多应用而言,Series最重要的一个功能是,它会根据运算的索引标签自动对齐数据,和数据库的join操作类似
serie有一个name属性,可以为数据和数据项起名

In [38]: obj4.name = 'population'

In [39]: obj4.index.name = 'state'

In [40]: obj4
Out[40]: 
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64

series的索引可以通过赋值的方式就地修改

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。
建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)

其中,panda里的head方法会选取前五行
如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列
如果传入的列在数据中找不到,就会在结果中产生缺失值
通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series
…………(把所有代码均进行了实现)

In [9]: 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]}

In [10]: frame = pd.DataFrame(data)

In [11]:  frame
Out[11]:
    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

In [12]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
Out[12]:
   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

In [13]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
    ...:    ....:                       index=['one', 'two', 'three', 'four',
    ...:                          ....:                              'five', 'six'])

In [14]: frame2
Out[14]:
       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

In [15]: frame2.state
Out[15]:
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: state, dtype: object

In [16]: frame2.debt=16.5

In [17]: frame2
Out[17]:
       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

In [18]: frame2['debt'] = np.arange(6.)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-18-f6c7820e8a60> in <module>
----> 1 frame2['debt'] = np.arange(6.)

NameError: name 'np' is not defined

In [19]: import numpy as np

In [20]: frame2['debt'] = np.arange(6.)

In [21]: frame2
Out[21]:
       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

In [22]: frame2['eastern'] = frame2.state == 'Ohio'

In [23]: frame2
Out[23]:
       year   state  pop  debt  eastern
one    2000    Ohio  1.5   0.0     True
two    2001    Ohio  1.7   1.0     True
three  2002    Ohio  3.6   2.0     True
four   2001  Nevada  2.4   3.0    False
five   2002  Nevada  2.9   4.0    False
six    2003  Nevada  3.2   5.0    False

In [24]: del frame2['eastern']

In [25]: frame2
Out[25]:
       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

In [26]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
    ...: ....:        'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

In [27]: frame3 = pd.DataFrame(pop)

In [28]: frame3
Out[28]:
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2000     NaN   1.5

索引对象

不可变的属性,可以使index在不同的数据结构之间共享

基本功能

重新索引

丢弃指定轴上的项

丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象

索引、选取和过滤

利用标签的切片运算与普通的Python切片运算不同,其末端是包含的

In [125]: obj['b':'c']
Out[125]:
b    1.0
c    2.0
dtype: float64

学习了以下代码

In [82]: data[:2]
Out[82]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7

In [83]: data
Out[83]:
          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

In [84]: data[data['three'] > 5]
Out[84]:
          one  two  three  four
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

In [85]: data < 5
Out[85]:
            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

In [86]:  data[data < 5] = 0

In [87]: data
Out[87]:
          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

用loc和iloc进行选取

对于DataFrame的行的标签索引,我引入了特殊的标签运算符loc和iloc。它们可以让你用类似NumPy的标记,使用轴标签(loc)或整数索引(iloc),从DataFrame选择行和列的子集
表5-4 DataFrame的索引选项

整数索引

由于歧义问题,


In [93]:     ser = pd.Series(np.arange(3.))

In [94]: ser
Out[94]:
0    0.0
1    1.0
2    2.0
dtype: float64

In [95]: ser[-1]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexes\range.py in get_loc(self, key, method, tolerance)
    384                 try:
--> 385                     return self._range.index(new_key)
    386                 except ValueError as err:

ValueError: -1 is not in range

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
<ipython-input-95-44969a759c20> in <module>
----> 1 ser[-1]

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\series.py in __getitem__(self, key)
    940
    941         elif key_is_scalar:
--> 942             return self._get_value(key)
    943
    944         if is_hashable(key):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\series.py in _get_value(self, label, takeable)
   1049
   1050         # Similar to Index.get_value, but we do not fall back to positional
-> 1051         loc = self.index.get_loc(label)
   1052         return self.index._get_values_for_loc(self, loc, label)
   1053

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexes\range.py in get_loc(self, key, method, tolerance)
    385                     return self._range.index(new_key)
    386                 except ValueError as err:
--> 387                     raise KeyError(key) from err
    388             raise KeyError(key)
    389         return super().get_loc(key, method=method, tolerance=tolerance)

KeyError: -1

对于非整数索引,不会产生歧义,为了进行统一,如果轴索引含有整数,数据选取总会使用标签。为了更准确,请使用loc(标签)或iloc(整数)
(本人实验认证,浮点型也会产生歧义)

算术运算和数据对齐

pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于有数据库经验的用户,这就像在索引标签上进行自动外连接
在两个数据相加时自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播
对于DataFrame,对齐操作会同时发生在行和列上

In [127]: df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'),
     ...:    .....:                    index=['Ohio', 'Texas', 'Colorado'])

In [128]: df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
     ...:    .....:                    index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [129]: df1
Out[129]:
            b    c    d
Ohio      0.0  1.0  2.0
Texas     3.0  4.0  5.0
Colorado  6.0  7.0  8.0

In [130]: df2
Out[130]:
          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

In [131]: df1+df2
Out[131]:
            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

在算术方法中填充值

可以使用df1的add方法,传入df2以及一个fill_value参数,这样会把缺失的值默认为0进行累加
表5-5 灵活的算术方法

DataFrame和Series之间的运算

当我们从arr减去arr[1],每一行都会执行这个操作。这就叫做广播(broadcasting)

In [136]: arr = np.arange(12.).reshape((3, 4))

In [137]: arr
Out[137]:
array([[ 0.,  1.,  2.,  3.],
       [ 4.,  5.,  6.,  7.],
       [ 8.,  9., 10., 11.]])

In [138]: arr[1]
Out[138]: array([4., 5., 6., 7.])

In [139]: arr-arr[1]
Out[139]:
array([[-4., -4., -4., -4.],
       [ 0.,  0.,  0.,  0.],
       [ 4.,  4.,  4.,  4.]])

函数应用和映射

NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象

In [190]: frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
   .....:                      index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [191]: frame
Out[191]: 
               b         d         e
Utah   -0.204708  0.478943 -0.519439
Ohio   -0.555730  1.965781  1.393406
Texas   0.092908  0.281746  0.769023
Oregon  1.246435  1.007189 -1.296221

In [192]: np.abs(frame)
Out[192]: 
               b         d         e
Utah    0.204708  0.478943  0.519439
Ohio    0.555730  1.965781  1.393406
Texas   0.092908  0.281746  0.769023
Oregon  1.246435  1.007189  1.296221

这里写入代码是为了说明其中(np.random.randn(4, 3))意思是创造一组4*3的矩阵,里面数据具有标准正态分布

In [193]: f = lambda x: x.max() - x.min()

In [194]: frame.apply(f)
Out[194]: 
b    1.802165
d    1.684034
e    2.689627
dtype: float64

这里lambda是个匿名函数

In [195]: frame.apply(f, axis='columns')
Out[195]:
Utah      0.998382
Ohio      2.521511
Texas     0.676115
Oregon    2.542656
dtype: float64

这里的axis='columns'是为了告诉计算机我选择行了而非列

排序和排名

根据条件对数据集排序(sorting)也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可使用sort_index方法,它将返回一个已排序的新对象
对于DataFrame,则可以根据任意一个轴上的索引进行排序
数据默认是按升序排序的,但也可以降序排序:

frame.sort_index(axis=1, ascending=False)

若要按值对Series进行排序,可使用其sort_values方法,在排序时,任何缺失值默认都会被放到Series的末尾
当排序一个DataFrame时,你可能希望根据一个或多个列中的值进行排序。将一个或多个列的名字传递给sort_values的by选项即可达到该目的

In [163]: frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})

In [164]: frame
Out[164]:
   b  a
0  4  0
1  7  1
2 -3  0
3  2  1

In [165]:  frame.sort_values(by='b')
Out[165]:
   b  a
2 -3  0
3  2  1
0  4  0
1  7  1

带有重复标签的轴索引

对于带有重复值的索引,数据选取的行为将会有些不同。如果某个索引对应多个值,则返回一个Series;而对应单个值的,则返回一个标量值
这样会使代码变复杂,因为索引的输出类型会根据标签是否有重复发生变化。
对DataFrame的行进行索引时也是如此

汇总和计算描述统计

(终于肝到这里,中间没忍住刷了好几次B站)

相关系数与协方差

有些汇总统计(如相关系数和协方差)是通过参数对计算出来的。书中的几个DataFrame,它们的数据来自Yahoo!Finance的股票价格和成交量,使用的是pandas-datareader包(可以用conda或pip安装)
conda install pandas-datareader
书中使用pandas_datareader模块下载了一些股票数据,可惜书中使用的网站是雅虎,雅虎现在已经凉了,所以暂时没有合适的数据,只好硬啃,相关内容都是概率论中各个理论的实现,除了介绍不同的方法以外,并没有新的东西

唯一值、值计数以及成员资格

还有一类方法可以从一维Series的值中抽取信息。
表5-9 唯一值、值计数、成员资格方法
有时,你可能希望得到DataFrame中多个相关列的一张柱状图。

In [20]: data = pd.DataFrame({'Qu1': [1, 3, 4, 3, 4],
    ...:    .....:                      'Qu2': [2, 3, 1, 2, 3],
    ...:                         .....:                      'Qu3': [1, 5, 2, 4, 4]})

In [21]: data
Out[21]:
   Qu1  Qu2  Qu3
0    1    2    1
1    3    3    5
2    4    1    2
3    3    2    4
4    4    3    4

In [22]: result = data.apply(pd.value_counts).fillna(0)

In [23]: result
Out[23]:
   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

这里,结果中的行标签是所有列的唯一值。后面的频率值是每个列中这些值的相应计数

小结

书中内容:
在下一章,我们将讨论用pandas读取(或加载)和写入数据集的工具。
之后,我们将更深入地研究使用pandas进行数据清洗、规整、分析和可视化工具。

通过学习numpy和pandas一些基础应用,了解到Numpy实际上是数值计算的扩展包,它能高效处理N维数组,复杂函数,线性代数.而Panadas是做数据处理,是python的一个数据分析包。同时更深刻了解了一些重要模块的使用,在不同库下调用的区别

明天继续努力!

posted @ 2022-03-15 22:17  Lugendary  阅读(28)  评论(0编辑  收藏  举报