第四章 Python 数据处理


第四章 Python 数据处理

1、numpy 数组操作

1.1 numpy 库概述

1.1.1 引言
  1. Python 中用列表(list)保存一组值,可用来当作数组使用,由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。为保存一个简单的[1,2,3],需要有 3 个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU计算时间
  2. 此外 Python 还提供了一个 array 模块,array 对象和列表不同,它直接保存数值,和 C 语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。
  3. numpy 的诞生弥补了这些不足,numpy 提供 ndarray(N-dimensional array object)对象:ndarray 是存储单一数据类型的多维数组。
1.1.2 numpy(Numerical Python的简称)

是高性能科学计算和数据分析的基础包,支持维度数组与矩阵运算。包括:

  1. 一个强大的 N 维数组对象 ndarray,具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。
  2. 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。
  3. 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。
  4. 线性代数、随机数生成以及傅里叶变换等功能。
  5. 用于集成由 C、C++、Fortran 等语言编写的代码的工具。
1.1.3 numpy 库提供了大量的库函数和操作

可以帮助程序员轻松地进行数值计算。这类数值计算广泛用于以下任务:

  1. 机器学习模型:在编写机器学习算法时,需要对矩阵进行各种数值计算。例如矩阵乘法、加法等。使用 numpy 库可进行简单(在编写代码方面)和快速(在速度方面)计算。numpy 数组用于存储训练数据和机器学习模型的参数。
  2. 图像处理和计算机图形学:计算机中的图像表示为多维数字数组,numpy 提供了一些优秀的库函数来快速处理图像。例如,镜像图像、按特定角度旋转图像等。
  3. 数学任务:numpy 可进行数值积分、微分、内插、外推等操作。numpy 库形成了一种基于 Python 的 MATLAB 的快速替代。

1.2 numpy 库安装

1.2.1 使用已有的发行版本
  1. 对于许多用户,尤其是 Windows 用户,最简单的方法是下载Python 发行版,包含所有的关键包(包括 numpy,SciPy,matplotlib 以及 Python 核心自带的其它包):
  2. Anaconda: 免费 Python 发行版,用于进行大规模数据处理、预测分析,和科学计算,致力于简化包的管理和部署。支持 Linux, Windows 和 Mac 系统。(推荐)
  3. Enthought Canopy: 提供了免费和商业发行版。持 Linux, Windows 和 Mac 系统。
  4. WinPython: 免费的 Python 发行版,包含科学计算包与 Spyder IDE。支持 Windows。
  5. Pyzo: 基于 Anaconda 的免费发行版本及 IEP 的交互开发环境,超轻量级。 支持Linux, Windows 和 Mac 系统。
1.2.2 使用 pip 安装
  1. 安装 numpy 最简单的方法就是使用 pip 工具:
    python -m pip install --user numpy  
  2. --user 选项可以设置只安装在当前的用户下,而不是写入到系统目录。

1.3 ndarray 概述

  1. N 维数组对象 ndarray 是用于存放同类型元素的多维数组。
  2. ndarray 中的每个元素在内存中都有相同存储大小的区域。
  3. ndarray 中的每个元素是数据类型对象的对象 ( 称为 dtype)。
  4. 与 Python 中的其他容器对象一样,可以通过对数组进行索引或切片。
  5. 可通过 ndarray 的方法和属性来访问和修改 ndarray 的内容 。

1.4 ndarray 之创建数组

1.4.1 创建 ndarray:创建数组最简单的办法就是使用 array 函数。

它接受一切序列型的对象,然后产生一个含有传入数据的 numpy 数组。其中,嵌套序列(比如由一组等长列表组成的列表)将会被转换为一个多维数组。

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
名称 描述
object 数组或嵌套的数列
dtype 数组元素的数据类型,可选
copy 对象是否需要复制,可选
order 创建数组的样式,C 为行方向,F 为列方向,A 为任意方向(默认)
subok 默认返回一个与基类类型一致的数组
ndmin 指定生成数组的最小维度
>>> import numpy as np
>>> a = [1, 2, 3, 4]   # 创建简单的列表
>>> b = np.array(a)    # 将列表转换为数组
>>> b
array([1, 2, 3, 4])
>>> c = np.array([[1,  2],  [3,  4]]) 
>>>c
[[1, 2] 
[3, 4]] 
1.4.2 除了np.array之外,还有一些函数也可以新建数组:
  1. zeros 和 ones 分别可以创建指定长度或者形状的全 0 或全 1 数组
  2. empty 可以创建一个没有任何具体值的数组
>>> np.zeros(3)  # 全 0 一维数组
array([ 0.,  0.,  0.])
>>> np.ones(3)   # 全 1 一维数组
array([ 1.,  1.,  1.])
>>> np.zeros((3,3))   # 全 0 二维数组,3 行 3 列
array([[ 0.,  0.,  0.],
    [ 0.,  0.,  0.],
    [ 0.,  0.,  0.]])
>>> np.zeros((3,1))   # 全 0 二维数组,3 行 1 列
array([[ 0.],
    [ 0.],
    [ 0.]])
>>> np.zeros((1,3))  # 全 0 二维数组,1 行 3 列
array([[ 0.,  0.,  0.]]) 
>>> np.ones((3,3))   # 全 1 二维数组,3 行 3 列
array([[ 1.,  1.,  1.],
    [ 1.,  1.,  1.],
    [ 1.,  1.,  1.]])
>>> np.ones((1,3))     # 全 1 二维数组,1 行 3 列
array([[ 1.,  1.,  1.]]) 
>>> np.identity(3)     # 单位矩阵,3 行 3 列
array([[ 1.,  0.,  0.],
    [ 0.,  1.,  0.],
    [ 0.,  0.,  1.]])
1.4.3 创建随机数组
  1. 均匀分布
    1) np.random.rand(10, 10) 创建指定形状(示例为10行10列)的数组(范围在0至1之间)
    2) np.random.uniform(0, 100) 创建指定范围内的一个数
    3) np.random.randint(0, 100) 创建指定范围内的一个整数

  2. 正态分布
    1) np.random.normal(1.75, 0.1, (2, 3)) 给定均值/标准差/维度的正态分布

>>> np.random.randint(0, 50, 5) # 随机数组,5个0到50之间的数字
array([13, 47, 31, 26,  9])
>>> np.random.randint(0, 50, (3,5)) # 3行5列,共15个随机整数,都介于[0,50]
array([[44, 34, 35, 28, 18],
    [24, 24, 26,  4, 21],
    [30, 40,  1, 24, 17]])
>>> np.random.rand(10)  # 10个介于[0,1)的随机数
array([ 0.58193552,  0.11106142,  0.13848858,  0.61148304,  0.72031503,0.12807841,  0.49999167,  0.24124012,  0.15236595,  0.54568207])
>>> np.random.standard_normal(5) # 从标准正态分布中随机采样5个数字
array([2.82669067, 0.9773194, -0.72595951, -0.11343254, 0.74813065])
1.4.4 查看数组属性的用法
用法 说明
b.size 数组元素个数
b.shape 数组形状
b.ndim 数组维度
b.dtype 数组元素类型
b.Itemsize 数组元素字节大小
1.4.5 查看数组属性的用法
import numpy as np

x = np.array([(1,2,3),(4,5,6)]) 
print(x)
print(x.size)
print(x.ndim)
print(x.shape)
print(x.itemsize)
print(x.dtype,'\n')

y = x.reshape(3,2)
print(y,'\n')
print(y.shape)

1.5 数组和标量之间的运算

数组很重要,因为它可以使我们不用编写循环即可对数据执行批量运算。这通常叫做矢量化(vectorization)。大小相等的数组之间的任何算术运算都会将运算应用到元素级。同样,数组与标量的算术运算也会将那个标量值传播到各个元素。

>>> arr = np.array([[1., 2., 3.], [4., 5., 6.]]) >>> arr
array([[1., 2., 3.],
>>> 1 / arr 
array([[1., 0.5, 0.33333333],   
    [0.25, 0.2, 0.16666667]])
>>> arr - arr 
array([[0., 0., 0.],
    [0., 0., 0.]])
>>> arr * arr 
array([[ 1.,  4.,  9.],    
    [16., 25., 36.]])
>>> arr ** 0.5
array([[1., 1.41421356, 1.73205081],    
    [2., 2.23606798, 2.44948974]])

1.6 基本的索引和切片

  1. 选取数据子集或的单个元素的方式有很多。
  2. 一维数组很简单,从表面上看,它们跟 Python 列表的功能差不多。
  3. 一维数组跟列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,数组视图上的任何修改都会直接反映到原始数组上。
  4. 将一个标量值赋值给一个切片时,该值会自动传播到整个选区。
>>> arr = np.arange(10)
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
>>> arr[5]
5
>>> arr[5:8]
array([5, 6, 7])
>>> arr[5:8] = 12
>>> arr
array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9]) 
>>> arr_slice = arr[5:8]
>>> arr_slice[1] = 12345
>>> arr
array([ 0, 1,  2,  3,  4, 12, 12345, 12,  8,  9]) 
>>> arr_slice[:] = 64
>>> arr
array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])
  1. 在二维数组中,各索引位置上的元素不再是标量而是一维数组。
  2. 可以对各个元素进行递归访问,但是这样有点麻烦。
  3. 还有一种方式是传入一个以逗号隔开的索引列表来选取单个元素。
  4. 在多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的 ndarray。
>>> arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
>>> arr3d
array([[[ 1,  2,  3],
    [ 4,  5,  6]],
    [[ 7,  8,  9],
    [10, 11, 12]]])
>>> arr3d[0] 
array([[1, 2, 3],
    [4, 5, 6]])
>>> arr3d[0][1] 
    array([4, 5, 6])

1.7 数学和统计方法

  1. 基本数组统计方法
    可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。
方法 说明
sum 对数组中全部或某轴向的元素求和。零长度的数组的sum 为 0
mean 算术平均数。零长度的数组的 mean 为 NaN。
std, var 分别为标准差和方差,自由度可调(默认为n)
min, max 最大值和最小值
argmin, argmax 分别为最大和最小元素的索引
cumsum 所有元素的累加
cumprod 所有元素的累积
  1. sum、mean 以及标准差 std 等聚合计算既可以当做数组的实例方法调用,也可以当做顶级 numpy 函数使用。
>>> arr = np.random.randn(5, 4) # 5行4列正态分布的数据
>>> arr.mean()
-0.022341797127577216 
>>> np.mean(arr)
-0.022341797127577216 
>>> arr.sum()
-0.44683594255154435
  1. mean 和 sum 这类的函数可以接受一个 axis 参数(用于计算该轴向上的统计值)。
>>> arr.mean(axis=1)
array([-0.11320162, -0.032351  , -0.24522299,  0.13275031,  0.14631631]) 
>>> arr.sum(0)
array([-1.71093252,  3.4431099 , -1.78081725, -0.39819607])
# 数学和统计方法
import numpy as np

arr = np.random.randn(5, 4) # 正态分布的数据
print(arr, '\n')
print(arr.mean(), '\n')
print(np.mean(arr), '\n')
print(arr.sum(), '\n')
print(arr.mean(axis = 0), '\n') # 按列
print(arr.mean(axis = 1), '\n') # 按行
print(arr.sum(0), '\n')
print(arr.sum(1), '\n')

b = np.array(arr[0])
print(arr[0])
print(b.mean())

运行结果

[[-0.80010107  1.07708638 -1.35612627 -0.0968496 ]
 [ 1.19282733 -0.76803973  0.96541953 -0.92755397]
 [ 0.1632381   0.20535389 -0.40766701 -1.59165831]
 [ 0.82877811  2.36588387  1.93749325 -0.59130029]
 [ 2.00014605 -2.02632033  0.98467712 -0.12523931]] 

0.15150238691579443 

0.15150238691579443 

3.0300477383158886 

[ 0.6769777   0.17079282  0.42475933 -0.6665203 ] 

[-0.29399764  0.11566329 -0.40768333  1.13521373  0.20831588] 

[ 3.38488852  0.85396408  2.12379663 -3.33260149] 

[-1.17599056  0.46265316 -1.63073333  4.54085494  0.83326354] 

[-0.80010107  1.07708638 -1.35612627 -0.0968496 ]
-0.29399764052791716
  1. cumsum
    按照所给定的轴参数返回元素的梯形累计和,axis=0,按照行累加。axis=1,按照列累加。

  2. cumprod
    按照所给定的轴参数返回元素的梯形累计乘积,axis=0,按照行累积。 axis=1,按照列累积。

>>> arr = np.array([[0, 1 ,2], [3, 4, 5], [6, 7, 8]]) 
>>> arr.cumsum(0)
array([[ 0,  1,  2],
[ 3,  5,  7],
[ 9, 12, 15]], dtype=int32)
>>> arr.cumprod(1)
array([[  0,   0,   0],
    [  3,  12,  60],
    [  6,  42, 336]], dtype=int32)

2、numpy 矩阵操作

2.1 numpy 矩阵库(Matrix)

  1. NumPy 中包含了一个矩阵库 numpy.matlib,该模块中的函数返回的是一个矩阵,而不是 ndarray 对象。

  2. 一个𝑚x𝑛的矩阵是一个由 𝑚行(row)𝑛 列(column)元素排列成的矩形阵列。

  3. 矩阵里的元素可以是数字、符号或数学式。以下是一个由6个数字元素构成的2行3列的矩阵:$\begin{bmatrix}1 & 9 & -13\20 & 5 & -6 \end{bmatrix} $

  4. NumPy 和 Matlab 不一样 , 对于多维数组的运算 , 缺省情况下并不使用矩阵运算 ,如果你希望对数组进行矩阵运算的话 , 可以调用ndarry对象相应的函数

2.2 numpy矩阵生成

  1. 常规方式生成
import numpy as np

x = np.matrix([[1,2,3], [4,5,6]])
y = np.matrix([1,2,3,4,5,6])
# x[0,0]返回行下标和列下标都为0的元素
# 注意,对于矩阵x来说,x[0,0]和x[0][0]的含义不一样
print(x, y, x[0,0],x[0][0],sep='\n\n')

运行结果

[[1 2 3]
 [4 5 6]]

[[1 2 3 4 5 6]]

1

[[1 2 3]]
  1. matlib.empty()

numpy.matlib.empty(shape, dtype, order)

shape: 定义新矩阵形状的整数或整数元组
Dtype: 可选,数据类型
order: C(行序优先) 或者 F(列序优先)

import numpy.matlib 
import numpy as np

print (np.matlib.empty((1,2))) # 填充为随机数据

运行结果
[[-6.04134793e-125 1.10846539e-274]]

  1. numpy.matlib.zeros()

  2. numpy.matlib.ones()
    ➢ numpy.matlib.zeros() 函数创建一个以 0 填充的矩阵。
    ➢ numpy.matlib.ones() 函数创建一个以 1 填充的矩阵。

import numpy.matlib 
import numpy as np 
print (np.matlib.zeros((2,2))) 
print (np.matlib.ones((2,2)))

运行结果
[[0. 0.]
[0. 0.]]
[[1. 1.]
[1. 1.]]

  1. numpy.matlib.eye()
    numpy.matlib.eye() 函数返回一个矩阵,对角线元素为 1,其他位置为零。

numpy.matlib.eye(n, M, k, dtype)
n: 返回矩阵的行数
M: 返回矩阵的列数,默认为 n
k: 对角线的索引
dtype: 数据类型

import numpy.matlib 
import numpy as np 

print (np.matlib.eye(n =  3, M =  4, k =  0, dtype =  int))

运行结果
[[1 0 0 0]
[0 1 0 0]
[0 0 1 0]]

  1. numpy.matlib.identity():返回给定大小的单位矩阵
    单位矩阵是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为 1,除此以外全都为 0。

$$I_1=[1],I_2=\begin{bmatrix}1 & 0\0 &1\end{bmatrix},I_3=\begin{bmatrix}1 & 0 & 0\0 & 1 & 0\0 & 0 & 1\end{bmatrix},…,$$

$$I_n=\begin{bmatrix}1 & 0 & … & 0\ 0 & 1 & … & 0\. & . & . & .\. & . & . & .\ . & . & . & . \0 & 0 & … & 1 \end{bmatrix}$$

import numpy.matlib 
import numpy as np 

# 大小为4,类型为整型
print (np.matlib.identity(4, dtype = int))

运行结果
[[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]]

  1. numpy.matlib.rand()
    numpy.matlib.rand() 函数创建一个给定大小的矩阵,数据是随机填充的。
import numpy.matlib 
import numpy as np 

print (np.matlib.rand(4,4))

运行结果
[[0.32525881 0.19282243 0.63614484 0.19132335]
[0.89759542 0.2546368 0.129491 0.87191412]
[0.71666597 0.48077184 0.80972151 0.30165613]
[0.34678005 0.39324507 0.8171954 0.53549778]]

2.3 numpy矩阵常用操作

2.3.1 矩阵与二维数组相互转换

矩阵总是二维的,而 ndarray 是一个 n 维数组。 两个对象都是可互换的。

import numpy.matlib 
import numpy as np  

i = np.matrix('1,2;3,4') 
print(i)
j = np.asarray(i) 
print(j)
k = np.asmatrix (j)  
print (k)

运行结果
[[1 2]
[3 4]]
[[1 2]
[3 4]]
[[1 2]
[3 4]]

2.3.2 矩阵转置
import numpy as np

x = np.matrix([[1,2,3], [4,5,6]]) 
y = np.matrix([1,2,3,4,5,6]) 
print(x.T, y.T, sep='\n\n')

运行结果
[[1 4]
[2 5]
[3 6]]

[[1]
[2]
[3]
[4]
[5]
[6]]

2.3.3 查看矩阵特征
import numpy as np

x = np.matrix([[1,2,3], [4,5,6]]) 

print(x.mean(), end='\n====\n') # 所有元素平均值

print(x.mean(axis=0), end='\n====\n')   # 纵向平均值

print(x.mean(axis=0).shape, end='\n====\n')

print(x.mean(axis=1), end='\n====\n')  # 横向平均值

print(x.sum(), end='\n====\n')  # 所有元素之和   

print(x.max(axis=1), end='\n====\n')  # 横向最大值

print(x.argmax(axis=1), end='\n====\n') # 横向最大值的下标

print(x.diagonal(), end='\n====\n')  # 对角线元素

运行结果

3.5
====
[[2.5 3.5 4.5]]
====
(1, 3)
====
[[2.]
 [5.]]
====
21
====
[[3]
 [6]]
====
[[2]
 [2]]
====
[[1 5]]
====
2.3.4 矩阵乘法

$A=\left(a_{ij}\right)^{m,p}{i,j=1},B=\left(b{ij}\right)^{p,n}{i,j=1},C=\left(c{ij}\right)^{m,n}{i,j=1},c{ij}=\sum\limits_{k=1}^p{a_{ik}b_{kj}}$

import numpy as np

x = np.matrix([[1,2,3], [4,5,6]]) 
y = np.matrix([[1,2], [3,4], [5,6]]) 
print(x*y)

运行结果
[[22 28]
[49 64]]

2.4 矩阵运算

  1. numpy.linalg 中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西

  2. 它们跟 MATLAB 和 R 等语言所使用的是相同的行业标准级Fortran库

  3. 常用的 numpy.linalg 函数:

函数 说明
diag 以一维数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换为方阵(非对角线元素为0)
dot 矩阵乘法
trace 计算对角线元素的和
det 计算矩阵行列式
eig 计算方阵的特征值和特征向量
inv 计算方阵的逆
svd 计算奇异值分解(SVD)
solve 解线性方程组Ax=b,其中A为一个方阵
lstsq 计算Ax=b的最小二乘解
2.4.1 numpy.dot()——两个数组的点积,即元素对应相乘
  1. 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积)。

  2. 对于二维数组,计算的是两个数组的矩阵乘积。

  3. 对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组 a 的最后一维上的所有元素与数组 b 的倒数第二位上的所有元素的乘积和:

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])

numpy.dot(a, b, out=None)
a : ndarray 数组
b : ndarray 数组
out : ndarray, 可选,用来保存 dot() 的计算结果

2.4.2 numpy.dot()示例

计算式为:[[111+213, 112+214],[311+413, 312+414]]

import numpy.matlib 
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]]) 
print(np.dot(a,b))

运行结果
[[37 40]
[85 92]]

2.4.3 numpy.vdot()——返回两个向量的点积

如果第一个参数是复数,那么它的共轭复数会用于计算。如果参数是多维数组,它会被展开。

计算式为:111 + 212 + 313 + 414 = 130

import numpy as np 

a = np.array([[1,2],[3,4]]) 
b = np.array([[11,12],[13,14]]) 

# vdot 将数组展开计算内积
print (np.vdot(a,b))

运行结果
130

2.4.4 numpy.linalg.inv()——计算逆矩阵

逆矩阵(inverse matrix):设 A 是数域上的一个 n 阶矩阵,若在相同数域上存在另一个 n 阶矩阵 B,使得: AB=BA=E ,则我们称 B 是 A 的逆矩阵,而 A 则被称为可逆矩阵。注:E 为单位矩阵。

import numpy as np 

x = np.array([[1,2],[3,4]]) 
y = np.linalg.inv(x) 
print (x)
print (y)
print (np.dot(x,y))

运行结果
[[1 2]
[3 4]]
[[-2. 1. ]
[ 1.5 -0.5]]
[[1.00000000e+00 1.11022302e-16]
[0.00000000e+00 1.00000000e+00]]

2.4.5 numpy.linalg.solve()——求矩阵形式的线性方程的解

线性方程组
$$\begin{cases}
a_{11}x_1&+&a_{12}x_2&+&\cdots&+a_{1n}x_n&=&b_1\
a_{21}x_1&+&a_{22}x_2&+&\cdots&+a_{2n}x_n&=&b_2&\
&&&&\vdots\
a_{n1}x_1&+&a_{n2}x_2&+&\cdots&+a_{nn}x_n&=&b_n&
\end{cases}$$

可以写作矩阵相乘的形式 ax=b。
其中,a 为 n×n 的矩阵,x 和 b 为 m×1 的矩阵。

2.4.6 numpy.linalg.solve()示例

$$\begin{cases}
x+y+z=6\
2y+5z=-4\
2x+5y-z=27
\end{cases} $$

转换成 $\begin{bmatrix}1 & 1 & 1\0 & 2 & 5\2 & 5 & -1\end{bmatrix}\begin{bmatrix}x\y\z \end{bmatrix}=\begin{bmatrix}6\-4\27 \end{bmatrix}$

import numpy as np

a = np.array([[1,1,1], [0,2,5],[2,5,-1]])   # 系数矩阵
b = np.array([6,-4,27])  # 系数矩阵
x = np.linalg.solve(a, b)  # 求解
print(x)
print(np.dot(a, x))    # 验证

运行结果
[ 5. 3. -2.]
[ 6. -4. 27.]

3、pandas 数据结构

3.1 引言

  1. Pandas 是基于 NumPy 的一种工具 , 该工具是为了解决数据分析任务而创建的。

  2. Pandas 纳入了大量库和一些标准的数据模型 ,提供了高效地操作大型数据集所需的工具。

  3. Pandas 提供了大量能使我们快速便捷地处理数据的函数和方法

  4. Pandas 是 Python 的一个数据分析包 ,最初于 2008 年 4 月开发 ,2009 年底开源 ,目前由 PyData 开发团队继续开发和维护。

5.Pandas 最初被作为金融数据分析工具而开发出来,也为时间序列分析提供了很好的支持。

3.2 pandas库介绍

  1. pandas 是 python 第三方库,提供高性能易用数据类型和分析工具。

  2. pandas 基于 numpy 实现,常与 numpy 和 matplotlib 一同使用。

  3. pandas 中有两大核心数据结构:Series (一维数据) 和 DataFrame(多特征数据,既有行索引,又有列索引)。

Series

DataFrame

  1. Series
    1)一维数组,与 Numpy 中的一维 array 类似 。
    2)Series、numpy 中的一维 array 与 Python 基本的数据结构 List 也很相近, 其区别是: List 中的元素可以是不同的数据类型,而 array 和 Series 中则只允许存储相同的数据类型。
    3)Series可以更有效的使用内存 , 提高运算效率。

  2. Time-Series:以时间为索引的Series。

  3. DataFrame:带标签且大小可变的二维表格型数据结构,可以将 DataFrame 理解为 Series 的容器。

  4. Panel:三维的数组,可以理解为DataFrame的容器。

3.3 Series

  1. Series 是一种类似于一维数组的对象,它由一维数组(各种 numpy 数据类型)以及一组与之相关的数据标签(即索引)组成。

  2. Series 创建函数:

pandas.Series( data, index, dtype, copy)

参数 描述
data 数据采取各种形式,如:adarraylistconstants
index 索引值必须是唯一的和散列的,与数据的长度相同。默认 np.arange(n) 如果没有索引被传递。
dtype dtype 用于数据类型,如果没有,将推断数据类型
copy 复制数据,默认为 false
  1. Series 的创建:
    1)使用 Python 数组创建
    2)使用 numpy 数组创建
    3)使用 python 字典创建

注意
与字典不同的是:Series允许索引重复

import pandas as pd
import numpy as np

pd.Series([11, 12], index=["北京", "上海"])

运行结果
北京 11
上海 12
dtype: int64

pd.Series(np.arange(3,6))

运行结果
0 3
1 4
2 5
dtype: int32

pd.Series({"北京": 11, "上海": 12, "深圳": 14})

运行结果
北京 11
上海 12
深圳 14
dtype: int64

  1. Series 的字符串表现形式为:索引在左边,值在右边

  2. 如果没有为数据指定索引,则自动创建一个 0 到 N-1(N 为数据的长度)的整数型索引。

  3. 可以通过 Series 的 values 和 index 属性获取其数组表示形式和索引对象。

>>> obj = pd.Series([4, 7, -5, 3]) 
>>> obj.values
array([ 4,  7, -5,  3], dtype=int64) 
>>> obj.index
RangeIndex(start=0, stop=4, step=1)


>>> obj[2]
-5
>>> obj[1] = 8 
>>> obj[[0, 1, 3]]
0    4
1    8
3    3
dtype: int64
  1. 通常希望所创建的 Series 带有一个可以对各个数据点进行标记的索引。

  2. 与普通 NumPy 数组相比,可以通过索引的方式选取 Series 中的单个或一组值。

>>> obj2=pd.Series([4,2,-5,3],index=['a', 'b', 'c', 'd'])
>>> obj2
a    4
b    2
c   -5
d    3
dtype: int64
>>> obj2['a']
4
>>> obj2['d'] = 6 
>>> obj2
a    4
b    2
c   -5
d    6
dtype: int64
>>> obj2[['a','b','d']]
a    4
b    2
d    6
dtype: int64
  1. Series 中很重要的一个功能是:它会在算术运算中自动对齐不同索引的数据。
>>> obj2 = pd.Series({"Ohio": 35000, "Oregon": 16000, "Texas": 71000, "Utah": 5000})
>>> obj3 = pd.Series({"California": np.nan, "Ohio": 35000, "Oregon": 16000, "Texas": 71000})
>>> obj2 + obj3
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah               NaN
dtype: float64
  1. Series 对象本身及其索引都有一个 name 属性

  2. Series 的索引可以通过赋值的方式就地修改

>>> obj3.name= 'population' 
>>> obj3.index.name = 'state' 
>>> obj3
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64
>>> obj = pd.Series([4, 7, -5, 3])
>>> obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan'] 
>>> obj
Bob      4
Steve    7
Jeff    -5
Ryan     3
dtype: int64

3.4 DataFrame

3.4.1 DataFrame介绍
  1. DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。
  2. DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共用同一个索引)。
  3. 跟其他类似的数据结构相比(如 R 语言的 data.frame),DataFrame 中面向行和面向列的操作基本上是平衡的。
  4. DataFrame 中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。
3.4.2 DataFrame特点
  1. 潜在的列是不同的类型
  2. 大小可变
  3. 标记轴( ( 行和列) )
  4. 可以对行和列执行算术运算
3.4.3 DataFrame示例

学生数据
学生数据

3.4.4 DataFrame构造函数

pandas.DataFrame( data, index, columns, dtype, copy)

参数 描述
data 数据采取各种形式,如:ndarray, series, map, lists, dict, constant 和另一个 DataFrame
index 对于行标签,要用于结果帧的索引是可选缺省值 np.arrange(n),如果没有传递索引值
columns 对于列标签,可选的默认语法是—— np.arange(n)。这只有在没有索引传递的情况下才是这样
dtype 每列的数据类型
copy 如果默认值为 False,则此命令(或任何它)用于复制数据
3.4.5 DataFrame
  1. 创建一个空的 DataFrame:函数不指定参数返回空 DataFrame
# 创建一个空的DataFrame 
import pandas as pd

df = pd.DataFrame() 
print(df)

运行结果
Empty DataFrame
Columns: []
Index: []

  1. 从列表创建 DataFrame
# 从单个列表创建DataFrame
data = [1,2,3,4]
df = pd.DataFrame(data) 
print(df)

运行结果

   0
0  1
1  2
2  3
3  4
# 从嵌套列表创建DataFrame、并指定数据类型
data = [['Alex',10],['Bob',12],['Clarke',13]]
df = pd.DataFrame(data,columns=['Name','Age'],dtype=float) 
print(df)

运行结果

     Name   Age
0    Alex  10.0
1     Bob  12.0
2  Clarke  13.0
  1. 由等长列表或 numpy 数组组成的字典创建 DataFrame。

  2. DataFrame 结果会自动加上索引(跟 Series 一样),且全部会被有序排列。

>>> data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'year': [2000 , 2001, 2002, 2001, 2002], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
>>> frame = pd.DataFrame(data)
>>> 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
  1. 如果指定了列顺序,则 DataFrame 的列就会按照指定顺序进行排列。

  2. 跟原 Series 一样,如果传入的列在数据中找不到,就会产生 NAN 值。

>>> 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
>>> frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'], index=['one', 'two', 'three', 'four', 'five'])
>>> 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
>>> frame2.columns

运行结果
Index([‘year’, ‘state’, ‘pop’, ‘debt’], dtype=’object’)

  1. 通过类似字典标记的方式或属性的方式,可以将 DataFrame 的列获取为一个 Series。

  2. 返回的 Series 拥有原 DataFrame 相同的索引,且其 name 属性也已经被相应地设置好了。

>>> frame2['state']

运行结果

one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
Name: state, dtype: object
>>> frame2['year']

运行结果

one      2000
two      2001
three    2002
four     2001
five     2002
Name: year, dtype: int64
  1. 列可以通过赋值的方式进行修改。

  2. 例如,给那个空的“delt”列赋上一个标量值或一组值。

>>> 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
>>> frame2['debt'] = np.arange(5.) 
>>> 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
  1. 将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。

  2. 如果赋值的是一个 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
  1. 为不存在的列赋值会创建出一个新列

  2. 关键字 del 用于删除列

>>> 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
>>> del frame2['eastern']
>>> frame2.columns

运行结果
Index([‘year’, ‘state’, ‘pop’, ‘debt’], dtype=’object’)

  1. 将嵌套字典(也就是字典的字典)传给 DataFrame,它就会被解释为:外层字典的键作为列,内层键则作为行索引。

  2. 也可以对上述结果进行转置。

>>> pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
>>> frame3 = pd.DataFrame(pop)
>>> frame3

运行结果

        Nevada    Ohio
2001     2.4    1.7
2002     2.9    3.6
2000     NaN    1.5
>>> frame3.T

运行结果

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

运行结果

state    Nevada    Ohio
year        
2001    2.4        1.7
2002    2.9        3.6
2000    NaN        1.5
  1. 跟 Series 一样,values 属性也会以二维 ndarray 的形式返回 DataFrame 中的数据。

  2. 如果 DataFrame 各列的数据类型不同,则数组的数据类型就会选用能兼容所有列的数据类型。

>>> frame3.values

运行结果

array([[2.4, 1.7],
       [2.9, 3.6],
       [nan, 1.5]])
>>> 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]], dtype=object)

4、pandas 常用方法

4.1 数据读取与写入

  1. Pandas 支持常用的文本格式数据(csv、json、html、剪贴板)、二进制数据(excel、hdf5 格式、Feather 格式、Parquet 格式、Msgpack、 Stata、SAS、pkl)、SQL 数据(SQL、谷歌 BigQuery 云数据)等。

  2. 一般情况下 , 读取文件的方法以 pd.read_ 开头, 而写入文件的方法以 pd.to_ 开头。

  3. 示例1

# 示例1,读入剪贴板数据,写入csv,转换为json、html、excel等格式
import pandas as pd
import numpy as np
from pandas import Series, DataFrame

# 粘贴板内容
#    A    B    C
# x    1    4    p
# y    2    5    q
# z    3    6    r

# 从粘贴板读取数据
df1 = pd.read_clipboard()

# 把数据放入到粘贴板中,数据可以直接粘贴到 excel 文件中
df1.to_clipboard()

# 读写 csv 文件,可以取消 index
df1.to_csv('df1.csv')
df1.to_csv('df1_noIndex.csv', index = False)

# 转化为 json 格式
df1.to_json('df1.json')

# 转化为 html 格式
df1.to_html('df1.html')

# 转换为 excel 格式
df1.to_excel('df1.xlsx')
数据类型 描述符 读方法 写方法
text CSV read_csv to_csv
text JSON read_json to_json
text HTML read_csv to_csv
text 剪切板 read_clipboard to_clipboard
二进制 Excel read_excel to_excel
二进制 HDF5 read_hdf to_hdf
二进制 PKL read_pickle to_pickle
SQL SQL read_sql to_sql

数据读取函数read_csv示例

  1. read_csv()

  2. 自定义索引:可以指定 csv 文件中的一列来使用 index_col 定制索引

  3. dtype:数据类型转换

  4. skiprows:跳过指定的行数

  5. 示例2

# 示例 2-1 read_csv
df=pd.read_csv('temp.csv') 
print(df)

运行结果

   S.No    Name  Agw       City  Salary
0     1     Tom   28    Toronto   20000
1     2     Lee   32   HongKong    3000
2     3  Steven   43   Bay Area    8300
3     4     Ram   38  Hyderabad    3900
# 示例 2-2  自定义索引:可以指定 csv 文件中的一列来使用 index_col 指定索引
df = pd.read_csv("temp.csv", index_col=['S.No']) 
print(df)

运行结果

        Name  Agw       City  Salary
S.No                                
1        Tom   28    Toronto   20000
2        Lee   32   HongKong    3000
3     Steven   43   Bay Area    8300
4        Ram   38  Hyderabad    3900
# 示例 2-3 转换器 dtype
df = pd.read_csv("temp.csv", dtype={'Salary': np.float64}) 
print(df) 
print(df.dtypes)

运行结果

   S.No    Name  Agw       City   Salary
0     1     Tom   28    Toronto  20000.0
1     2     Lee   32   HongKong   3000.0
2     3  Steven   43   Bay Area   8300.0
3     4     Ram   38  Hyderabad   3900.0
S.No        int64
Name       object
Agw         int64
City       object
Salary    float64
dtype: object
# 示例 2-4  使用 names参数指定标题名称
df=pd.read_csv("temp.csv", names=['a', 'b', 'c','d','e']) 
print(df)

运行结果

      a       b    c          d       e
0  S.No    Name  Agw       City  Salary
1     1     Tom   28    Toronto   20000
2     2     Lee   32   HongKong    3000
3     3  Steven   43   Bay Area    8300
4     4     Ram   38  Hyderabad    3900

观察可以看到,标题名称附加了自定义名称,但文件中的标题还没有被消除。现在使用header参数来删除它。如果标题不是第一行,则将行号传递给标题,这将跳过前面的行。

# 示例 2-5消除文件中的标题
df=pd.read_csv("temp.csv", names=['a', 'b', 'c','d','e'], header=0) 
print(df)

运行结果

   a       b   c          d      e
0  1     Tom  28    Toronto  20000
1  2     Lee  32   HongKong   3000
2  3  Steven  43   Bay Area   8300
3  4     Ram  38  Hyderabad   3900
# 示例 2-6 skiprows跳过指定的行数
df=pd.read_csv("temp.csv", skiprows=2) 
print (df)

运行结果

   2     Lee  32   HongKong  3000
0  3  Steven  43   Bay Area  8300
1  4     Ram  38  Hyderabad  3900

4.2 描述性统计方法

  1. Pandas 提供了几个统计和描述性方法,方便你从宏观的角度去了解数据集,例如count() 用于统计非空数据的数量。

  2. 除了统计类的方法,Pandas 还 提供了很多计算类的方法,比如 sum() 用于计算数值数据的总和;mean() 用 于 计 算 数 值 数 据 的 平 均 值 ;median() 用于计算数值数据的算术中值。

函数 描述
count() 非空观测数量
sum() 所有值之和
mean() 所有值的平均值
median() 所有值的中位数
mode() 值的模值
std() 值的标准偏差
min() 所有值中的最小值
max() 所有值中的最大值
abs() 绝对值
prod() 数组元素的乘积
cumsum() 累计总和
cumprod() 累计乘积

描述性统计方法示例
sum():求和;
mean() :求中值;
std():求标准差;
describe():描述性统计信息摘要。

# 示例3 描述统计方法
import pandas as pd
import numpy as np

# Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Minsu','Jack','Lee','David','Gasper','Betina','Andres']),'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])}

#Create a DataFrame
df = pd.DataFrame(d)
print(df, '\n')
print("\n列求和")
print(df.sum(), '\n')  # 列求和, 默认axis=0.

print("\n行求和")
print(df.sum(1), '\n')   # 行求和,axis=1

print("\n求均值")
print(df.mean(), '\n')   # 求均值

print("\n标准差")
print(df.std(), '\n')    # 标准差

# include参数是用于传递关于什么列需要考虑用于总结的必要信息的参数,获取值列表,默认情况下是“数字值”。
# object - 汇总字符串列;
# number - 汇总数字列;
# all - 将所有列汇总在一起(不应将其作为列表值传递)。

print("\n统计信息摘要")
print(df.describe(include=['number']))    # 统计信息摘要

运行结果

      Name   Age  Rating
0      Tom   25    4.23
1    James   26    3.24
2    Ricky   25    3.98
3      Vin   23    2.56
4    Steve   30    3.20
5    Minsu   29    4.60
6     Jack   23    3.80
7      Lee   34    3.78
8    David   40    2.98
9   Gasper   30    4.80
10  Betina   51    4.10
11  Andres   46    3.65 


列求和
Name      TomJamesRickyVinSteveMinsuJackLeeDavidGasperBe...
Age                                                     382
Rating                                                44.92
dtype: object 


行求和
0     29.23
1     29.24
2     28.98
3     25.56
4     33.20
5     33.60
6     26.80
7     37.78
8     42.98
9     34.80
10    55.10
11    49.65
dtype: float64 


求均值
Age       31.833333
Rating     3.743333
dtype: float64 


标准差
Age       9.232682
Rating    0.661628
dtype: float64 


统计信息摘要
             Age     Rating
count  12.000000  12.000000
mean   31.833333   3.743333
std     9.232682   0.661628
min    23.000000   2.560000
25%    25.000000   3.230000
50%    29.500000   3.790000
75%    35.500000   4.132500
max    51.000000   4.800000

4.3 迭代与遍历

  1. pandas 对象之间的基本迭代的行为取决于类型。当迭代一个系列时,它被视为数组式,基本迭代产生这些值。其他数据结构,如:DataFrame,遵循类似惯例迭代对象的键。

  2. 简而言之,基本迭代(对于 i 在对象中)产生:
    ➢ Series - 值
    ➢ DataFrame - 列标签

  3. 要遍历数据帧(DataFrame)中的行,可以使用以下函数:
    ➢ iteritems() - 迭代(key,value)对
    ➢ iterrows() - 将行迭代为(索引,系列)对
    ➢ itertuples() - 以 namedtuples 的形式迭代行

4.3.1 迭代 DataFrame
# 迭代 DataFrame
import pandas as pd
import numpy as np

N=5
df = pd.DataFrame({
    'D': pd.date_range(start='2019-01-01',periods=N,freq='M'), 
    'x': np.linspace(0,stop=N-1,num=N),
    'y': np.random.rand(N),
    'z': np.random.choice(['Low','Medium','High'],N).tolist(),
})

print(df,'\n')

for col in df:
    print(col)

运行结果

           D    x         y       z
0 2019-01-31  0.0  0.088484    High
1 2019-02-28  1.0  0.763299    High
2 2019-03-31  2.0  0.918397    High
3 2019-04-30  3.0  0.785687  Medium
4 2019-05-31  4.0  0.821885     Low 

D
x
y
z
4.3.2 遍历Dataframe 示例
  1. iteritems():将索引和值作为键和列值迭代为 Series 对象。
  2. iterrows():返回迭代器,产生每个索引值以及包含每行数据的序列。
  3. itertuples():方法将为 DataFrame 中的每一行返回一个产生一个命名元组的迭代器。元组的第一个元素将是行的相应索引值,而剩余的值是行值。
# 遍历 iteritems()将每个列作为名称,将索引和值作为键和列值迭代为Series对象
df = pd.DataFrame(np.random.randn(4,3), columns=['col1','col2','col3'])

print(df, '\n')

print("\niteritems---------")
for key,value in df.iteritems():  
    print (key,value)

# iterrows()返回迭代数器,产生每个索引值以及包含每行数据的序列
print("\niterrows---------")
for row_index,row in df.iterrows():    
    print (row_index,row)

# itertuples()方法将为 DataFrame 中的每一行返回一个产生一个命名元组的迭代器。元组的第一个元素将是行的相应索引值,而剩余的值是行值
print("\nitertuples---------")
for row in df.itertuples():    
    print (row)

运行结果

       col1      col2      col3
0  0.769239 -0.321667  0.229970
1 -0.414440 -0.686365 -1.804574
2 -0.625321 -0.410545 -0.266878
3  0.942061 -0.429502 -0.191403 


iteritems---------
col1 0    0.769239
1   -0.414440
2   -0.625321
3    0.942061
Name: col1, dtype: float64
col2 0   -0.321667
1   -0.686365
2   -0.410545
3   -0.429502
Name: col2, dtype: float64
col3 0    0.229970
1   -1.804574
2   -0.266878
3   -0.191403
Name: col3, dtype: float64

iterrows---------
0 col1    0.769239
col2   -0.321667
col3    0.229970
Name: 0, dtype: float64
1 col1   -0.414440
col2   -0.686365
col3   -1.804574
Name: 1, dtype: float64
2 col1   -0.625321
col2   -0.410545
col3   -0.266878
Name: 2, dtype: float64
3 col1    0.942061
col2   -0.429502
col3   -0.191403
Name: 3, dtype: float64

itertuples---------
Pandas(Index=0, col1=0.7692393725888382, col2=-0.3216667049027107, col3=0.22996991034224118)
Pandas(Index=1, col1=-0.41444004324475786, col2=-0.6863646340873751, col3=-1.8045739966582113)
Pandas(Index=2, col1=-0.625321480205094, col2=-0.4105445003436983, col3=-0.2668784127256191)
Pandas(Index=3, col1=0.9420608482646933, col2=-0.4295015650195585, col3=-0.191402644416027)
​

4.4 排序

  1. 按索引排序:使用 sort_index() 方法,通过传递 axis 参数和排序顺序,可以对 DataFrame 进行排序。 默认情况下,按照升序对行标签进行排序。

  2. 按数值排序:sort_values() 是按值排序的方法。它接受一个 by 参数,它将使用要与其排序值的 DataFrame 的列名称。

  3. 排序顺序:通过将布尔值传递给升序参数 ascending,可以控制排序顺序。

  4. 按行或列排序:通过设置 axis 参数为 0 或 1 ,为 0 时逐行排序,为 1 时逐列排序,默认为 0。

排序示例

print("\n待排序------")
unsorted_df = pd.DataFrame(np.random.rand(10,2),index=[1,4,6,2,3,5,9,8,0,7],columns = ['A','B'])
print(unsorted_df,'\n')

print("\n按索引排序------")
sorted_df=unsorted_df.sort_index(ascending = True)  #按索引排序
print (sorted_df,'\n')

print("\n按'B'列的值进行排序------")
sorted_df = unsorted_df.sort_values(by='B') # 按'B'列的值进行排序
print (sorted_df,'\n')

运行结果

待排序------
          A         B
1  0.301330  0.303682
4  0.955318  0.035809
6  0.254245  0.798225
2  0.408592  0.470527
3  0.885707  0.131258
5  0.135931  0.859795
9  0.934681  0.218391
8  0.992487  0.416087
0  0.221823  0.468366
7  0.414039  0.531079 


按索引排序------
          A         B
0  0.221823  0.468366
1  0.301330  0.303682
2  0.408592  0.470527
3  0.885707  0.131258
4  0.955318  0.035809
5  0.135931  0.859795
6  0.254245  0.798225
7  0.414039  0.531079
8  0.992487  0.416087
9  0.934681  0.218391 


按'B'列的值进行排序------
          A         B
4  0.955318  0.035809
3  0.885707  0.131258
9  0.934681  0.218391
1  0.301330  0.303682
8  0.992487  0.416087
0  0.221823  0.468366
2  0.408592  0.470527
7  0.414039  0.531079
6  0.254245  0.798225
5  0.135931  0.859795 

4.5 缺失值处理

  1. 缺失值主要是指数据丢失的现象,也就是数据集中的某一块数据不存在。

  2. 除了原始数据集就已经存在缺失值以外,当我们用到索引对齐(reindex(),选择等)方法时,也容易人为导致缺失值的产生。

  3. 缺失值处理包括:
    ➢ 缺失值标记
    ➢ 缺失值填充
    ➢ 缺失值插值

  4. Pandas 为了更方便地检测缺失值,将不同类型数据的缺失均采用 NaN 标记。这里的 NaN 代表 Not a Number ,它仅仅是作为一个标记。

  5. Pandas 中用于标记缺失值主要用到两个方法,分别是:isnull () 和 notnull (),顾名思义就是「是缺失值」和「不是缺失值」。默认会返回布尔值用于判断。

# 使用reindex()人为生成缺失值
df = pd.DataFrame(np.random.rand(4, 3), index=['a', 'c', 'e', 'f'],columns=['one', 'two', 'three'])
print('原始:\n', df,'\n')
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
print('reindex后:\n', df,'\n')

print(df['one'].isnull(),'\n')  # 缺失值标记
print (df['one'].notnull(),'\n')

运行结果

原始:
         one       two     three
a  0.051237  0.164315  0.632927
c  0.459356  0.435970  0.615046
e  0.420776  0.668942  0.680803
f  0.086104  0.409684  0.162472 

reindex后:
         one       two     three
a  0.051237  0.164315  0.632927
b       NaN       NaN       NaN
c  0.459356  0.435970  0.615046
d       NaN       NaN       NaN
e  0.420776  0.668942  0.680803
f  0.086104  0.409684  0.162472
g       NaN       NaN       NaN 

a    False
b     True
c    False
d     True
e    False
f    False
g     True
Name: one, dtype: bool 

a     True
b    False
c     True
d    False
e     True
f     True
g    False
Name: one, dtype: bool 
  1. Pandas 提供了各种方法来清除缺失的值。fillna() 函数可以通过几种方法用非空数据“填充” NaN 值。
    1)用标量值替换 NaN

print (df.fillna(0))

# 用标量填充
print("NaN replaced with '0':")
print(df.fillna(0))

运行结果

NaN replaced with '0':
        one       two     three
a  0.051237  0.164315  0.632927
b  0.000000  0.000000  0.000000
c  0.459356  0.435970  0.615046
d  0.000000  0.000000  0.000000
e  0.420776  0.668942  0.680803
f  0.086104  0.409684  0.162472
g  0.000000  0.000000  0.000000

2)向前填充:pad/fill
print(df.fillna(method=’pad’))

# 向前填充
print(df.fillna(method='pad'))

运行结果

        one       two     three
a  0.051237  0.164315  0.632927
b  0.051237  0.164315  0.632927
c  0.459356  0.435970  0.615046
d  0.459356  0.435970  0.615046
e  0.420776  0.668942  0.680803
f  0.086104  0.409684  0.162472
g  0.086104  0.409684  0.162472

3)向后填充:bfill/backfill
print(df.fillna(method=’backfill’))

# 向后填充
print (df.fillna(method='backfill'))

运行结果

        one       two     three
a  0.051237  0.164315  0.632927
b  0.459356  0.435970  0.615046
c  0.459356  0.435970  0.615046
d  0.420776  0.668942  0.680803
e  0.420776  0.668942  0.680803
f  0.086104  0.409684  0.162472
g       NaN       NaN       NaN
  1. 丢弃缺少的值:如果只想排除缺少的值,则使用 dropna 函数和 axis 参数。默认情况下,axis=0,如果行内的任何值是 NaN,那么整个行被删除。
    1)丢弃含 NaN 值的行

print(df.dropna())
2)丢弃含 NaN 值的列
print (df.dropna(axis=1))

df = pd.DataFrame(np.random.rand(4, 3), index=['a', 'c', 'e', 'f'], columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g'])

print(df,'\n')
print(df.dropna()) # 丢弃含 NaN 值的行
print (df.dropna(axis=1)) # 丢弃含 NaN 值的列

运行结果

        one       two     three
a  0.430961  0.718700  0.023831
b       NaN       NaN       NaN
c  0.560938  0.816387  0.409205
d       NaN       NaN       NaN
e  0.945503  0.838175  0.707113
f  0.987987  0.275285  0.532072
g       NaN       NaN       NaN 

        one       two     three
a  0.430961  0.718700  0.023831
c  0.560938  0.816387  0.409205
e  0.945503  0.838175  0.707113
f  0.987987  0.275285  0.532072
Empty DataFrame
Columns: []
Index: [a, b, c, d, e, f, g]
  1. 替换缺失(或通用)值:用一些具体的值取代一个通用的值或缺失值。用标量替换 NaN 和使用 fillna() 函数等效。
# 替换通用数据或者缺失值
df = pd.DataFrame({'one':[10,20,30,40,50,2000],'two':[1000,0,30,40,50,60]}) 
print(df,'\n')
print(df.replace({1000:10,2000:60}))

文章作者: 谢舟
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 谢舟 !
 上一篇
第五章 Python 数据可视化 第五章 Python 数据可视化
第五章 Python 数据可视化1、Matplotlib 基础1.1 Matplotlib 库介绍 Matplotlib 是 Python 最著名的绘图库,它提供了一整套和 Matlab 相似的命令 API,十分适合交互式地进行制图。而且也
2020-06-06
下一篇 
第三章 Python 编程进阶 第三章 Python 编程进阶
第三章 Python 编程进阶1、输入输出与文件操作 输入输出 基本输入、输出2. 文件操作文件编码、基本操作 1.1 输入 Python 提供了 input() 内置函数从标准输入读入一行文本。 input() 函数也可以接收一个 P
2020-06-02
  目录