pandas(1)

五迷三道 提交于 2020-02-06 05:24:43

《Python数据科学手册》读书笔记

安装并使用Pandas

import numpy as np
# 检查pandas的版本号
import pandas as pd
pd.__version__
'0.23.4'
pd?

Pandas对象简介

如果从底层视角观察Pandas,可以把它们看成增强版的Numpy结构化数组,行列都不再是简单的整数索引,还可以带上标签。

先来看看Pandas三个基本的数据结构:

  • Series
  • DataFrame
  • Index

Pandas的Series对象

Pandas的Series对象是一个带索引数据构成的一维数组,可以用一个数组创建Series对象

data = pd.Series([0.25, 0.5, 0.75, 1.0])
data
0    0.25
1    0.50
2    0.75
3    1.00
dtype: float64

我们可以通过values属性和index属性获取数据。values属性返回的结果和Numpy数组类似

data.values
array([0.25, 0.5 , 0.75, 1.  ])

index属性返回结果是一个类型为pd.Index的类数组对象

data.index
RangeIndex(start=0, stop=4, step=1)
data[1]
0.5
data[1:3]
1    0.50
2    0.75
dtype: float64

可以看出Pandas的Series对象比它模仿的一维Numpy数组更加通用

Series是广义的Numpy数组

Series对象和Numpy数组基本可以等价代换,但两者间的本质差异其实是索引:

  • Numpy数组通过隐式定义的整数索引获取数值
  • Series对象是一种显示定义的索引与数值关联

显示定义的索引让Series对象有了更加强大的能力。

例如:索引不再仅仅是整数,还可以是任意想要的类型

data = pd.Series([0.25, 0.5, 0.75, 1.0],
                 index=['a', 'b', 'c', 'd'])
data
a    0.25
b    0.50
c    0.75
d    1.00
dtype: float64
# 获取索引b的数值
data['b']
0.5

也可以使用不连续或者不按顺序的索引

data = pd.Series([0.25, 0.5, 0.75, 1.0],
                 index=[2, 5, 3, 7])
data
2    0.25
5    0.50
3    0.75
7    1.00
dtype: float64

Series是特殊的字典

字典是将任意键映射到一组任意值的结构,而Series对象是将类型化键映射到一组类型化值的结构。这种类型很重要:就像NumPy数组背后的特定类型编译代码使它在某些操作上比Python列表更有效一样,Series对象的类型信息使它在某些操作上比Python字典更有效。

可以直接用Python字典创建一个Series对象,让Series对象与字典进行类比

population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)
population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
dtype: int64

用字典创建Series对象时,其索引默认按照顺序排列

population['California']
38332521

和字典不同,Series对象还支持数组形式的操作

# 切片操作
population['California':'Illinois']
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
dtype: int64

创建Series对象

  • pd.Series(data, index=index)

其中index是一个可选参数,data参数支持多种数据类型

data可以是列表或者是Numpy数组,这时index默认值为整数数列:

pd.Series([2, 4, 6])
0    2
1    4
2    6
dtype: int64

data也可以是标量,这样创建Series对象时会重复填充到每个索引上:

pd.Series(5, index=[100, 200, 300])
100    5
200    5
300    5
dtype: int64

data还可以是一个字典,index默认是排序的字典键:

pd.Series({2:'a', 1:'b', 3:'c'})
2    a
1    b
3    c
dtype: object

每一种形式都可以通过显示指定索引筛选所需要的结果

# Series对象只会保留显示定义的键值对
pd.Series({2:'a', 1:'b', 3:'c'}, index=[3, 2])
3    c
2    a
dtype: object
# 当索引值长度大于data长度,自动用NaN填充
pd.Series({2:"a",1:'b',3:"c"},index={1,2,3,4})
1      b
2      a
3      c
4    NaN
dtype: object

Pandas的DataFrame对象

Pandas的另一个基础数据结构是DataFrame。和之前介绍的Series一样,DataFrame既可以作为一个通用型Numpy数组,也可以看做特殊的Python字典。

DataFrame是广义的Numpy数组

如果将Series 类比为带灵活索引的一维数组,那么DataFrame 就可以看作是一种既有灵活的行索引,又有灵活列索引的二维数组。就像你可以把二维数组看成是有序排列的一维数组一样,你也可以把DataFrame 看成是有序排列的若干Series 对象。这里的“排列”指的是它们拥有共同的索引。

area_dict = {'California': 423967, 'Texas': 695662, 'New York': 141297,
             'Florida': 170312, 'Illinois': 149995}
area = pd.Series(area_dict)
area
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
dtype: int64

再结合之前创建的population的Series对象,用一个字典创建一个包含以上信息的二维对象

states = pd.DataFrame({'population': population,
                       'area': area})
states
population area
California 38332521 423967
Texas 26448193 695662
New York 19651127 141297
Florida 19552860 170312
Illinois 12882135 149995
# 用index属性获取行索引标签
states.index
Index(['California', 'Texas', 'New York', 'Florida', 'Illinois'], dtype='object')
# 用columns属性获取列索引标签
states.columns
Index(['population', 'area'], dtype='object')

因此,DataFrame 可以看作一种通用的NumPy 二维数组,它的行与列都可以通过索引获取。

DataFrame是特殊的字典

与Series 类似,我们也可以把DataFrame 看成一种特殊的字典。字典是一个键映射一个值,而DataFrame 是一列映射一个Series 的数据。例如,通过’area’ 的列属性可以返回
包含面积数据的Series 对象:

# 面积数据
states['area']
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64

创建DataFrame对象

  1. 通过单个Series对象创建

给一个Series对象作为data,给定列名columns

pd.DataFrame(population, columns=['population'])
population
California 38332521
Texas 26448193
New York 19651127
Florida 19552860
Illinois 12882135
  1. 任何元素是字典的列表都可以变成DataFrame。用一个简单的列表综合来创建一些数据:
data = [{'a': i, 'b': 2 * i}
        for i in range(3)]
pd.DataFrame(data)
a b
0 0 0
1 1 2
2 2 4

即使字典中有些键不存在,Pandas 也会用缺失值NaN(不是数字,not a number)来表示:

pd.DataFrame([{'a': 1, 'b': 2}, {'b': 3, 'c': 4}])
a b c
0 1.0 2 NaN
1 NaN 3 4.0
  1. 通过Series对象字典创建

用一个字典创建,字典的value值为Series对象

pd.DataFrame({'population': population,
              'area': area})
population area
California 38332521 423967
Texas 26448193 695662
New York 19651127 141297
Florida 19552860 170312
Illinois 12882135 149995
  1. 通过NumPy二维数组创建

假如有一个二维数组,就可以创建一个可以指定行列索引值的DataFrame。如果不指定行列索引值,那么行列默认都是整数索引值:(本质是给一个多维Series对象,给定行索引index,给定列索引columus,默认为None)

pd.DataFrame(np.random.rand(3, 2),
             columns=['foo', 'bar'],
             index=['a', 'b', 'c'])
foo bar
a 0.611537 0.795093
b 0.789713 0.050002
c 0.209812 0.051797

Pandas的Index对象

Series 和DataFrame 对象都使用便于引用和调整的显式索引。Pandas 的
Index 对象是一个很有趣的数据结构,可以将它看作是一个不可变数组或有序集合

# 使用一个简单的列表创建Index对象
ind = pd.Index([2, 3, 5, 7, 11])
ind
Int64Index([2, 3, 5, 7, 11], dtype='int64')

将Index看作不可变数组

Index 对象的许多操作都像数组。例如,可以通过标准Python 的取值方法获取数值,也可以通过切片获取数值:

ind[1]
3
ind[::2]
Int64Index([2, 5, 11], dtype='int64')

Index对象有许多和Numpy数组相似的属性

print(ind.size, ind.shape, ind.ndim, ind.dtype)
5 (5,) 1 int64

Index对象的索引是不可逆的,也就是说不能通过赋值的方法进行调整

ind[1] = 0
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-49-906a9fa1424c> in <module>()
----> 1 ind[1] = 0


C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in __setitem__(self, key, value)
   2063 
   2064     def __setitem__(self, key, value):
-> 2065         raise TypeError("Index does not support mutable operations")
   2066 
   2067     def __getitem__(self, key):


TypeError: Index does not support mutable operations

Index 对象的不可变特征使得多个DataFrame 和数组之间进行索引共享时更加安全,尤其是可以避免因修改索引时粗心大意而导致的副作用。

将Index看作有序集合

Index对象可以求交集、并集

indA = pd.Index([1, 3, 5, 7, 9])
indB = pd.Index([2, 3, 5, 7, 11])
indA & indB  # 交集
Int64Index([3, 5, 7], dtype='int64')
indA | indB  # 并集
Int64Index([1, 2, 3, 5, 7, 9, 11], dtype='int64')
indA ^ indB  # 异或
Int64Index([1, 2, 9, 11], dtype='int64')

这些操作还可以通过调用对象方法来实现,例如 indA.intersection(indB)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!