支持常见的矩阵操作,通过ndarray类实现了对多位数据的封装,提供了对这些数组操作的方法和函数集.
由于Numpy支持并行运算的功能,因此使用多核CPU的时候,Numpy会自动进行并行运算
Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据).
Series类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成.
DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引).
绘图用的
Seaborn:基于Matplotlib的图形可视化工具,能让用户 做出各种统计图表
Seaborn的底层是基于Matplotlib的,他们的差异有点像在点餐时选套餐还是自己点的区别,Matplotlib是独立点菜,可能费时费心,但最后上桌的菜全是特别适合自己的;而Seaborn是点套餐,特别简单,一切都是配好的,虽然省时省心,但可能套餐里总有些菜是不那么合自己口味的。
Seaborn是用户把自己常用到的可视化绘图过程进行了函数封装,形成的一个“快捷方式”,他相比Matplotlib的好处是代码更简洁,可以用一行代码实现一个清晰好看的可视化输出。主要的缺点则是定制化能力会比较差,只能实现固化的一些可视化模板类型;
而Matplotlib是可以实现高度定制化绘图的,高度定制化可以让你获得最符合心意的可视化输出结果,但也因此需要设置更多的参数,因而代码更加复杂一些。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warning
#忽略所有的警告信息
warnings.filterwarnings('ignore')
%pwd
# 显示当前文件路径
% ls
# 显示文件详情
Numerical Python
# 法1
nums = [1, 2, 3, 4, 155]
array1 = np.array(nums, dtype='u8')
array1
# array([ 1, 2, 3, 4, 155], dtype=uint64)
# 数组的类型
type(array1)
# numpy.ndarray
# 数组的size属性 - 元素的个数
array1.size
# 5
# 数组的dtype属性 - 元素的数据类型
array1.dtype
# dtype('uint64')
# 数组的shape属性 - 数组的形状
array1.shape
# (5,)
# 数组的ndim属性 - 数组的维度(ndimension)
array1.ndim
# 1
# 数组的itemsize属性 - 每个元素占用的内存空间的大小(字节)
array1.itemsize
# 8
# 数组的nbytes属性 - 整个数组占用的内存空间的大小(字节)
array1.nbytes
# 40
# 将数组还原成Python中的列表
array1.tolist()
# [1, 2, 3, 4, 155]
array2 = np.arange(1,100,2)
#array([ 1, 3, 5, 7, 9, 11, 13, 15, #17, 19, 21, 23, 25, 27, 29, 31, 33,
# 35, 37, 39, 41, 43, 45, 47, 49, #51, 53, 55, 57, 59, 61, 63, 65, 67,
# 69, 71, 73, 75, 77, 79, 81, 83, #85, 87, 89, 91, 93, 95, 97, 99])
array3 = np.linspace(-5,5,num=100,endpoint=False)
#array([-5. , -4.9, -4.8, -4.7, -4.6, -4.5, -4.4, -4.3, -4.2, -4.1, -4. ,
# -3.9, -3.8, -3.7, -3.6, -3.5, -3.4, -3.3, -3.2, -3.1, -3. , -2.9,
# -2.8, -2.7, -2.6, -2.5, -2.4, -2.3, -2.2, -2.1, -2. , -1.9, -1.8,
# -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1. , -0.9, -0.8, -0.7,
# -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0. , 0.1, 0.2, 0.3, 0.4,
# 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4, 1.5,
# 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6,
# 2.7, 2.8, 2.9, 3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7,
# 3.8, 3.9, 4. , 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8,
# 4.9])
array4 = np.random.randint(60, 101, 15)
#array([95, 67, 78, 63, 84, 79, 87, 60, 91, 65, 92, 66, 93, 73, 70])
nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
array8 = np.array(nums)
#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
# 将一维数组调形成二维数组
array9 = array4.reshape((5, 3))
#array([[95, 67, 78],
# [63, 84, 79],
# [87, 60, 91],
# [65, 92, 66],
# [93, 73, 70]])
array11 = np.random.randint(60, 101, size=(5, 3))
#array([[66, 70, 91],
# [98, 79, 76],
# [84, 70, 79],
# [76, 91, 85],
# [88, 73, 84]])
np.zeros((3, 3), dtype='i8')
#array([[0, 0, 0],
# [0, 0, 0],
# [0, 0, 0]], dtype=int64)
np.ones((2, 2), dtype='i4')
#array([[1, 1],
# [1, 1]])
np.full((3, 3), 5)
#array([[5, 5, 5],
# [5, 5, 5],
# [5, 5, 5]])
# 创建二维数组对象(方法五)---> 单位矩阵
np.eye(3, dtype='i8')
#array([[1, 0, 0],
# [0, 1, 0],
# [0, 0, 1]], dtype=int64)
import random
scores = [[random.randrange(60, 101) for _ in range(3)] for _ in range(5)]
scores
# [[60, 83, 100], [77, 81, 92], [61, 100, 89], [93, 82, 94], [94, 68, 60]]
# 通过array把列表处理成数组
scores = np.array(scores)
scores
# array([[ 60, 83, 100],
# [ 77, 81, 92],
# [ 61, 100, 89],
# [ 93, 82, 94],
# [ 94, 68, 60]])
scores.mean(axis=1)
#[81. 83.33333333 83.33333333 89.66666667 74. ]
scores.max(axis=0)
# array([ 94, 100, 100])
scores.min(axis=0)
# array([60,68,60])
# 一维
array12 = np.random.randint(1, 100, 9)
# array([35, 23, 95, 85, 12, 26, 14, 22, 9])
# 二维
array13 = np.arange(1, 10).reshape((3, 3))
array13
#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
可以使用正向索引和负向索引,注意不要越界
array12[0], array12[8], array12[-1], array12[-9]
# 取出来是个元组
# (35, 9, 9, 35)
array13[0][1], array13[1][2]
#(2, 6)
使用布尔类型的数组充当索引,True对应的元素会保留,False对应的元素会过滤掉
array12[array12 > 50]
# array([100, 200, 95, 85, 300])
array12 % 2 != 0
# array([False, False, True, True, False, False, False, False, False])
array12[array12 % 2 != 0]
# array([95, 85])
# 从数组中取大于50的奇数
# 两个布尔数组是可以做逻辑运算(对应元素进行逻辑运算),但是不能用Python中的and、or、not
# 取而代之的是三个运算符:&、|、~
array12[(array12 > 50) & (array12 % 2 != 0)]
(fancing index)- 一次性操作多个索引对应的元素
# 一维
array12[[0, 2, 5, 7, 0, 0, -1, -1]]
# array([35, 95, 26, 22, 35, 35, 9, 9])
# 二维
array13[[0, 0, 1, 2, 2], [1, 2, 2, 2, 0]]
# array([2, 3, 6, 9, 7])
# 切片
# 一维
array12[[0, 1, -1]] = 100, 200, 300
#array([100, 200, 95, 85, 12, 26, 14, 22, 300])
array12[::-1]
#array([300, 22, 14, 26, 12, 85, 95, 200, 100])
# 二维
array13[:2, 1:]
# 切到第二行,从第一列开始
#array([[2, 3],
# [5, 6]])
array13[2, :]
# 从第二行开始,全切
array([7, 8, 9])
array13[::2, ::2]
# 间隔二行二列地切
#array([[1, 3],
# [7, 9]])
array14 = np.random.randint(100, 501, 12)
array14
# array([489, 475, 172, 436, 277, 338, 456, 303, 255, 430, 125, 391])
# 均值(集中趋势)---> 均值容易受到极端值的干扰
# 如何区分一个数据是正常的极端值还是异常值,主要的点是看数据是否能够重复稳定的出现
print(array14.mean())
print(np.mean(array14))
#345.5833333333333
#345.5833333333333
array14.sum()
# 4147
# numpy中的sort函数跟Python中的sorted类似,不会对原数组排序,而是返回排序后的数组对象
# 这种设计理念叫做函数的无副作用性设计(函数不能随意修改传入的对象的状态)
np.sort(array14)
# array([125, 172, 255, 277, 303, 338, 391, 430, 436, 456, 475, 489])
np.median(array14)
# 364.5
print(array14.max())
print(np.max(array14))
print(array14.min())
print(np.min(array14))
#489
#489
#125
#125
print(array14.max() - array14.min())
print(np.ptp(array14))
#364
#364
总体方差:
σ 2 = 1 N ∑ i = 1 N ( X i − μ ) 2 \sigma^2 = \frac{1}{N} \sum_{i=1}^N (X_i - \mu)^2 σ2=N1i=1∑N(Xi−μ)2
样本方差:
S 2 = 1 N − 1 ∑ i = 1 N ( X i − X ˉ ) 2 S^2 = \frac{1}{N - 1} \sum_{i=1}^N (X_i - \bar{X})^2 S2=N−11i=1∑N(Xi−Xˉ)2
总体标准差:
σ = 1 N ∑ i = 1 N ( X i − μ ) 2 \sigma = \sqrt{\frac{1}{N} \sum_{i=1}^N (X_i - \mu)^2} σ=N1i=1∑N(Xi−μ)2
样本标准差:
S = 1 N − 1 ∑ i = 1 N ( X i − X ˉ ) 2 S = \sqrt{\frac{1}{N - 1} \sum_{i=1}^N (X_i - \bar{X})^2} S=N−11i=1∑N(Xi−Xˉ)2
print(array14.var())
print(array14.std())
# 13370.07638888889
# 115.62904647574021
补充:四分位距离除了可以反映数据的集中或离散趋势外,还可以帮我们判定一个数据是否为异常值(极端值)。
D a t a < Q 1 − 1.5 × I Q R Data < Q1 - 1.5 \times IQR Data<Q1−1.5×IQR
D a t a > Q 3 + 1.5 × I Q R Data > Q3 + 1.5 \times IQR Data>Q3+1.5×IQR
# 上四分位数(75%分位数)
q3 = np.quantile(array14, 0.75)
# 下四分位数(25%分位数)
q1 = np.quantile(array14, 0.25)
# 四分位距离
iqr = q3 - q1
iqr
# 169.5
array15 = array14.astype(np.float64)
print(array15)
print(array15.dtype)
print(array14.dtype)
#[489. 475. 172. 436. 277. 338. 456. 303. 255. 430. 125. 391.]
#float64
#int32
# json数据的保存
import json
person = {'name': 'Hao', 'age': 41}
with open('person.json', 'w') as file:
json.dump(person, file)
# 产生了一个叫person的文件
# 将数组做pickle序列化并保存到文件中
array15.dump('array15')
# 产生了一个叫array15的文件
# 从文件中加载数组对象(pickle反序列化)
array16 = np.load('array15', allow_pickle=True)
array16
#array([489., 475., 172., 436., 277., 338., 456., 303., 255., 430., 125.,
# 391.])
array15 is array16
# False
array15 == array16
# array([ True, True, True, True, True, True, True, True, True,
# True, True, True])
array13.flatten()
# array([1, 2, 3, 4, 5, 6, 7, 8, 9])
array15.reshape((4, 3))
#array([[489., 475., 172.],
# [436., 277., 338.],
# [456., 303., 255.],
# [430., 125., 391.]])
array16 = array15.copy()
# 调整数组的大小(在数组上直接调整,缺失的值补0)
array16.resize((5, 3))
array16
#array([[489., 475., 172.],
# [436., 277., 338.],
# [456., 303., 255.],
# [430., 125., 391.],
# [ 0., 0., 0.]])
(返回新的数组对象,缺失的值用原数组的值填充)
np.resize(array15, (7, 3))
#array([[489., 475., 172.],
# [436., 277., 338.],
# [456., 303., 255.],
# [430., 125., 391.],
# [489., 475., 172.],
# [436., 277., 338.],
# [456., 303., 255.]])
# 就地排序(直接修改原数组)
array15.sort()
array15
和np.sort不一样的是.array.sort是就地修改
array17 = np.arange(1, 15, 2)
# array([ 1, 3, 5, 7, 9, 11, 13])
array18 = np.array([2, 2, 3, 3, 4, 4, 5])
# array([2, 2, 3, 3, 4, 4, 5])
array17 * array18
# array([ 2, 6, 15, 21, 36, 44, 65])
广播(broadcast)机制:当两个形状并不相同的数组进行运算时,NumPy会试图通过广播机制使得两个数组的形状变得一致。满足下列条件之一,才能使用广播机制:
array19 = np.array([[1, 2, 3], [4, 5, 6]])
# array([[1, 2, 3],
# [4, 5, 6]])
array20 = np.array([10, 20, 30])
array20
# array([10, 20, 30])
array19+array20
# array([[11, 22, 33],
# [14, 25, 36]])
array21 = np.array([[40], [40]])
# array([[40],
# [40]])
array19 + array21
# array([[41, 42, 43],
# [44, 45, 46]])
# nan ---> Not a Number
# inf ---> Infinity
temp = np.array([1, 2, np.nan, 3, -np.inf])
temp
# array([ 1., 2., nan, 3., -inf])
# isnan:判断有没有空值,产生布尔数组
temp[~np.isnan(temp)]
# array([ 1., 2., 3., -inf])
# isinf:判断无穷大值,产生布尔数组
np.isinf(temp)
# array([False, False, False, False, True])
array1 = np.array([1, 1, 2, 3, 5, 1, 1, 3, 5, 4])
# 去重
np.unique(array1)
# array([1, 2, 3, 4, 5])
array2 = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
array3 = np.array([[4, 4, 4], [5, 5, 5], [6, 6, 6]])
np.hstack((array2, array3))
#array([[1, 1, 1, 4, 4, 4],
# [2, 2, 2, 5, 5, 5],
# [3, 3, 3, 6, 6, 6]])
np.vstack((array2, array3))
#array([[1, 1, 1],
# [2, 2, 2],
# [3, 3, 3],
# [4, 4, 4],
# [5, 5, 5],
# [6, 6, 6]])
array4 = np.stack((array2, array3))
array4
# array([[[1, 1, 1],
# [2, 2, 2],
# [3, 3, 3]],
#
# [[4, 4, 4],
# [5, 5, 5],
# [6, 6, 6]]])
array4.shape
#(2,3,3)
array5 = np.stack((array2, array3), axis=1)
#array([[[1, 1, 1],
# [4, 4, 4]],
#
# [[2, 2, 2],
# [5, 5, 5]],
#
# [[3, 3, 3],
# [6, 6, 6]]])
array5.shape
# (3, 2, 3)
# 数组拼接
# axis=0 ---> 相当于是vstack
# axis=1 ---> 相当于是hstack
array6 = np.concatenate((array2, array3), axis=1)
array6
#array([[1, 1, 1, 4, 4, 4],
# [2, 2, 2, 5, 5, 5],
# [3, 3, 3, 6, 6, 6]])
# 在水平方向拆分数组,拆成俩
np.hsplit(array6, 2)
#[array([[1, 1, 1],
# [2, 2, 2],
# [3, 3, 3]]),
# array([[4, 4, 4],
# [5, 5, 5],
# [6, 6, 6]])
#]
# 在垂直方向拆,拆3个
np.vsplit(array6, 3)
#[array([[1, 1, 1, 4, 4, 4]]),
# array([[2, 2, 2, 5, 5, 5]]),
# array([[3, 3, 3, 6, 6, 6]])]
# 等同于
np.split(array6, 3, axis=0)
np.append(array6, 7)
# array([1, 1, 1, 4, 4, 4, 2, 2, 2, 5, 5, 5, 3, 3, 3, 6, 6, 6, 7])
np.insert(array6, 0, 8)
# array([8, 1, 1, 1, 4, 4, 4, 2, 2, 2, 5, 5, 5, 3, 3, 3, 6, 6, 6])
array7 = np.random.randint(1, 100, 10)
# array([16, 96, 89, 95, 42, 3, 22, 54, 86, 51])
np.extract(array7 > 50, array7)
# array([96, 89, 95, 54, 86, 51])
conds = [array7 < 30, array7 > 50]
choices = [array7 ** 2, array7 - 10]
# 按照设定的条件和处理数据的方式从数组中获取数据构成新数组
np.select(conds, choices)
np.where(array7 > 50, array7, array7 ** 2)
#array([ 256, 96, 89, 95, 1764, 9, 484, 54, 86, 51])
#设置value的显示长度为200,默认为50
pd.set_option('max_colwidth',200)
#显示所有列,把行显示设置成最大
pd.set_option('display.max_columns', None)
#显示所有行,把列显示设置成最大
pd.set_option('display.max_rows', None)
官方已经不建议使用matrix对象,建议使用的是普通ndarray对象表示矩阵
而且在将来的版本中,matrix类型可能会被移除掉
m1 = np.matrix('1 2 3; 4 5 6')
m1
#matrix([[1, 2, 3],
# [4, 5, 6]])
m2 = np.matrix([[2, 2], [3, 3], [4, 4]])
m2
#matrix([[2, 2],
# [3, 3],
# [4, 4]])
m3 = np.matrix(np.arange(1, 10).reshape(3, 3))
m3
# matrix([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
# 获得matrix对象对应的ndarray对象
m3.A
# array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
m3.A1
# array([1, 2, 3, 4, 5, 6, 7, 8, 9])
m3.T
#matrix([[1, 4, 7],
# [2, 5, 8],
# [3, 6, 9]])
np.linalg.det(m3)
# m3 ---> Singular matrix ---> 奇异矩阵 ---> 无法求逆矩阵
# m3.I
m5 = m4.I
和ndarray相乘不一样
m4.A * m5.A
# matmul ---> 实现矩阵乘法的函数
np.round(np.matmul(a4, a5), 1)
np.round(a4 @ a5, 1)
求解下面的线性方程组:用np求解的时候,只能求一个解的情况,无穷解和一个解都会报错
{ 3 x 1 + 5 x 2 = 4 x 1 + 2 x 2 = 1 {\begin{cases} 3x_{{1}}+5x_{{2}}=4\\ x_{{1}}+2x_{{2}}=1 \end{cases}} {3x1+5x2=4x1+2x2=1
a = np.array([[3, 5], [1, 2]])
b = np.array([4, 1]).reshape(-1, 1)
# 解线性方程组
np.linalg.solve(a, b)
# 无解 ---> LinAlgError ---> Singular matrix
# a = np.array([[1, 1], [2, 2]])
# b = np.array([2, 1]).reshape(-1, 1)
# np.linalg.solve(a, b)
# 无穷解 ---> LinAlgError ---> Singular matrix
# a = np.array([[1, 1], [2, 2]])
# b = np.array([2, 4]).reshape(-1, 1)
# np.linalg.solve(a, b)
# 线性方程组有解的条件 ---> 系数矩阵(|A|)的秩和增广矩阵(|Ab|)的秩相等
# 矩阵的秩 ---> 线性无关(不能通过其他向量做线性变换得到)的行向量的个数
# 计算矩阵的秩
np.linalg.matrix_rank(a)
# 获得增广矩阵
ab = np.hstack((a, b))
np.linalg.matrix_rank(ab)
a = np.array([[3, 1, 2], [1, -1, 4], [2, 0, 3]])
b = np.array([0, 0, 0]).reshape(-1, 1)
ab = np.hstack((a, b))
print(np.linalg.matrix_rank(a))
print(np.linalg.matrix_rank(ab))
Panel Data Set
Pandas中文网
三个核心的数据类型:
Series
—> 数据系列 —> 表示一维的数据DataFrame
—> 数据框/数据窗/数据表 —> 表示二维的数据(表格)Index
—> 索引 —> 为Series
和DataFrame
对象提供索引服务创建DataFrame对象
openpyxl
、xlwt
、xlrd
)pymysql
或mysqlclient
)DataFrame索引和切片
获取列:df['col_name']
/ df.col_name
—> Series
获取行:df.loc[row_index]
/ df.iloc[0]
—> Series
获取单元格:df.at[row_index, col_name]
/ df.iat[0, 1]
—> 值
切片:df.loc[row_index1:row_index2]
/ df.iloc[m:n:k]
/ df[m:n:k]
花式索引/布尔索引
基本方法:
info()
:查看DataFrame的相关信息head()
/ tail()
:查看前N条或后N条数据df.loc和df.iloc的区别:
loc使用范围比iloc更广泛实用,loc可以使用切片,名称(index,columns),也可以切片和名称混合使用;
loc不能使用不存在的索引充当切片取值,如:df.loc[-1]
iloc只能用整数来取值
可以把i看作是int
loc的使用范围高于iloc,loc也可以做到iloc的切片取数,除了df.loc[-1]
使用切片\索引\列名称查找.
按条件查找
# 切片
hy_data.loc[2:4,]
hy_data.loc[[0,1,2,3],:]
# 切片和名称混合
hy_data.loc[2:4,'用户编号']
# 按条件取数
# 表示取出df中“行业分类”列值的长度等于6的所有行
hy_data.loc[hy_data['行业分类'].str.len() == 6, :]
data就是表格中的数据,columns是列索引,index是行索引
df = pd.DataFrame(data=scores, columns=courses, index=names)
df
# 语文 数学 英语
# 白起 60 83 100
# 安琪拉 77 81 92
# 庄周 61 100 89
# 狄仁杰 93 82 94
# 李元芳 94 68 60
# 创建DataFrame的第一种方式(基于二维数组)
df1 = pd.DataFrame(
data=np.random.randint(60, 101, (5, 3)),
index=np.arange(1001, 1006),
columns=['语文', '数学', '英语']
)
df1
# 语文 数学 英语
# 1001 67 91 77
# 1002 82 94 79
# 1003 76 83 92
# 1004 63 87 72
# 1005 66 94 83
# 创建DataFrame的第二种方式(基于字典)
scores = {
'语文': [62, 72, 93, 88, 93],
'数学': [95, 65, 86, 66, 87],
'英语': [66, 75, 82, 69, 82],
}
df2 = pd.DataFrame(data=scores, index=np.arange(1001, 1006))
df2
# 语文 数学 英语
# 1001 62 95 66
# 1002 72 65 75
# 1003 93 86 82
# 1004 88 66 69
# 1005 93 87 82
# 创建DataFrame的第三种方法(读取CSV文件)
# read_csv函数的几个重要参数:
# ~ delimiter / sep:分隔符(默认是英文的逗号)
# ~ nrows:读取的行数
# ~ skiprows:跳过哪些行
# ~ usecols:指定读取哪些列
# ~ index_col:指定使用哪个列充当行索引
# ~ encoding:编码(解决乱码现象)
df3 = pd.read_csv(
r'data/2018年北京积分落户数据.csv',
index_col='id',
usecols=['id', 'name', 'score'],
sep=',',
nrows=10,
skiprows=np.arange(1, 11)
)
df3
# name score
#id
#11 张晓燕 115.45
#12 季进 115.29
#13 徐建安 115.25
#14 赵文学 115.21
#15 周鹏 115.13
#16 龚平 114.88
#17 姜秋梅 114.50
#18 潘阳发 114.42
#19 陈阵 113.67
#20 纪晓峰 113.67
# 创建DataFrame的第四种方法(读取Excel文件)
# header ---> 表头在什么位置(列索引)
# sheet_name ---> 指定读取哪个工作表
df4 = pd.read_excel(
'data/小宝剑大药房(犀浦店)2018年销售数据.xlsx',
header=1,
sheet_name='工作表1'
)
# 创建DataFrame的第五种方式(从MySQL数据库读取数据)
import pymysql
conn = pymysql.connect(host='47.104.31.138', port=3306,
user='guest', password='Guest.618',
database='hrs', charset='utf8mb4')
df5 = pd.read_sql('select dno, dname, dloc from tb_dept', conn)
# 关闭连接
conn.close()
df6 = pd.read_sql(
sql='select eno, ename, job, mgr, sal, comm, dno from tb_emp',
con=conn,
index_col='eno'
)
pd.merge(df6, df5, on='dno', how='inner')
DataFrame中单取某一列或者某一行,会得到Series对象
df6['ename']
沿1轴计算平均分,再将平均分加入表格
df[‘平均分’]=np.round(df.mean(axis=1),2)
df
df['平均分']=np.round(df.mean(axis=1),2)
# 相同类型才可以合并
df['test']=df['salary'].map(str)+df['education']
max_scores = df.max()
min_scores = df.min()
df.loc['最高分']=max_scores
#loc:取行
df.loc['最低分']=min_scores
df
pd.concat([df[:1],df[-1:len(df)]])
df.append(df.iloc[7])
data[data['日期'].isnull()]
for columname in data.columns:
if data[columname].count()!=len(data):
loc=data[columname][data[columname].isnull().value==True].index.tolist()
print('列名:"{}", 第{}行位置有缺失值'.format(columname,loc))
"""
axis:0-行操作,1-列操作
how:any-只要有空值就删除(默认),all-全部为空值才删除
inplace:False-返回新的数据集(默认),True-在原数据集上操作
"""
data.dropna(axis=0,how='any',inplace=True)
data_df=pd.DataFrame(columns=data.columns)
df = pd.DataFrame({'num_legs':[2,4],'num_wings':[2,0]},index=['falcon','dog'])
# num_legs num_wings
#falcon 2 2
#dog 4 0
df.isin({'num_wings':[0,3]})
# num_legs num_wings
#falcon False False
#dog False True
# 打印换手率为--的行
data[data['换手率(%)'].isin['--']]
Series.diff : Compute the difference of two elements in a Series.
DataFrame.diff : Compute the difference of two elements in a DataFrame.
Series.shift : Shift the index by some number of periods.
DataFrame.shift : Shift the index by some number of periods.
s = pd.Series([90, 91, 85])
s.pct_change()
#0 NaN
#1 0.011111
#2 -0.065934
#dtype: float64
获得信息轴
Series的索引,dataframe的列
# 创建Series对象(方法一)
ser1 = pd.Series(data=[420, 380, 520, 520, 230], index=[f'{x}季度' for x in '一二三三四'])
ser1
# 创建Series对象(方法二)
ser2 = pd.Series(data={
'一季度': 420,
'二季度': 380,
'三季度': 520,
'四季度': 500
})
ser2
ser1[1:3]
#二季度 380
#三季度 520
#dtype: int64
ser1['二季度':'三季度']
#二季度 380
#三季度 520
#三季度 520
#dtype: int64
ser1[['一季度', '四季度', '一季度']]
#一季度 420
#四季度 230
#一季度 420
#dtype: int64
ser1[ser1 > 400]
ser1.values
#array([420, 380, 520, 520, 230], dtype=int64)
ser1.index
# Index(['一季度', '二季度', '三季度', '三季度', '四季度'], dtype='object')
判断数值是否唯一,与索引无关
ser1.is_unique
# False
ser3.duplicated()
#0 False
#1 False
#2 True
#3 False
#4 False
#dtype: bool
ser3.drop_duplicates()
#0 apple
#1 banana
#3 pitaya
#4 peach
#dtype: object
# 设置保留哪一项
# 默认第一个
#last:最后一项
# False:只要重复就一个都不保留
ser3.drop_duplicates(keep='last')
ser3.drop_duplicates(keep=False)
ser1.hasnans
# False
ser1.is_monotonic_increasing
# False
ser1.sort_values(ascending=False)
ser1.sort_index(ascending=False)
ser3 = pd.Series(data=['apple','banana','apple','pitaya','peach'])
ser3.unique()
# array(['apple', 'banana', 'pitaya', 'peach'], dtype=object)
ser3.nunique()
# 4
ser3.value_counts()
# apple 2
# pitaya 1
# banana 1
# peach 1
# dtype: int64
ser3.isnull()
#0 False
#1 False
#2 False
#3 False
#4 False
#dtype: bool
ser3.notnull()
#0 True
#1 True
#2 True
#3 True
#4 True
#dtype: bool
ser3[1]=np.nan
ser3.dropna()
#0 apple
#2 apple
#3 pitaya
#4 peach
#dtype: object
# 指定填补
ser3.fillna('orange')
# 用前一个值填充空值
ser3.fillna(method='ffill')
# 用后一个填充空值
ser3.fillna(method='bfill')
ser4 = pd.Series(np.random.randint(1,100,6))
ser4
#0 75
#1 47
#2 3
#3 84
#4 29
#5 8
#dtype: int32
where
满足条件的保留
# where:把满足条件的数据保留,不满足条件的数据替换
# 把小于30的置为空
ser4.where(ser4>30)
#0 75.0
#1 47.0
#2 NaN
#3 84.0
#4 NaN
#5 NaN
#dtype: float64
# 把小于30的替换成30
ser4.where(ser4>30,30)
#0 75
#1 47
#2 30
#3 84
#4 30
#5 30
#dtype: int32
mask
满足条件的替换
# mask:把满足条件的替换,不满足的保留
ser4.mask(ser4>30,30)
#0 30
#1 30
#2 3
#3 30
#4 29
#5 8
#dtype: int32
ser1.at['一季度']
# 420
ser1.iat[0]
# 420
ser1.loc[['一季度','三季度']]
#一季度 420
#三季度 500
#三季度 430
#dtype: int64
ser1.iloc[[0,3,4]]
#一季度 420
#三季度 500
#三季度 430
#dtype: int64
ser1.sum()
#2780
ser1.describe()['mean']
# 397.1428...
# 极差,最大值和最小值的差
np.ptp(ser1)
# 270
# 众数,数组没有这个方法,系列上有
ser1.mode()
#0 500
#dtype: int64
# 只拿第一个众数
ser1.mode()[0]
# 500
ser5 = pd.Series(['cat','dog',np.nan,'rabbit'])
#0 cat
#1 dog
#2 NaN
#3 rabbit
#dtype: object
# 映射
ser5.map({'cat':'kitty','dog':'puppy'})
#0 kitty
#1 puppy
#2 NaN
#3 NaN
#dtype: object
ser6 = pd.Series(data=['32','89','100','56','47'])
#0 32
#1 89
#2 100
#3 56
#4 47
#dtype: object
ser6.map(int).mean
#0 32
#1 89
#2 100
#3 56
#4 47
#dtype: int64>
ser6.apply(lambda x:round(int(x)**0.5*10,1))
线性归一化(标准化):把数据转换到0-1之间的值
X ∗ = X i − X m i n X m a x − X m i n X^{*} = \frac{X_i - X_{min}}{X_{max}-X_{min}} X∗=Xmax−XminXi−Xmin
X ∗ = X i − μ σ X^{*}=\frac{X_i - \mu}{\sigma} X∗=σXi−μ
ser1 = pd.Series(data=[420,380,520,520,230],index=[f'{x}季度'for x in '一二三三四'])
#一季度 420
#二季度 380
#三季度 520
#三季度 520
#四季度 230
#dtype: int64
# 对ser1进行线性归一化
x_min=min(ser1)
x_max=max(ser1)
ser1.apply(lambda x:((x-x_min)/(x_max-x_min)))
#一季度 0.655172
#二季度 0.517241
#三季度 1.000000
#三季度 1.000000
#四季度 0.000000
#dtype: float64
# 对ser1进行零均值归一化
mu,sigma = ser1.mean(),ser1.std()
ser1.apply(lambda x:(x-mu)/sigma)
#一季度 0.050035
#二季度 -0.283530
#三季度 0.883947
#三季度 0.883947
#四季度 -1.534399
#dtype: float64
ser1.nlargest(3)
#三季度 520
#三季度 520
#一季度 420
#dtype: int64
# 最小的两个
ser1.nsmallest(2)
#四季度 230
#二季度 380
#dtype: int64
ser1.groupby(level=0).sum()
#一季度 420
#三季度 1040
#二季度 380
#四季度 230
#dtype: int64
df['salary'].astype(np.float64)
len(df[df['salary']>10000])
移动窗口就是窗口向一端滑行,默认是从右往左,每次滑行并不是区间整块的滑行,而是一个单位一个单位的滑行。
首先我们设置的窗口window=3,也就是3个数取一个均值。index 0,1 为NaN,是因为它们前面都不够3个数,等到index2 的时候,它的值是怎么算的呢,就是(index0+index1+index2 )/3
index3 的值就是( index1+index2+index3)/ 3
作用:5日均线,10日均线…
data['收盘价(元)'].rolling(5).sum()
# 将收盘价5日均线、20日均线与原始数据绘制在同一个图上
data['收盘价(元)'].plot()
data['收盘价(元)'].rolling(5).mean().plot()
data['收盘价(元)'].rolling(20).mean().plot()
对原样本重新处理,对一个常规时间序列数据重新采样和频率转换
# 绘制重新采样数据和原始数据
data['收盘价(元)'].plot()
data['收盘价(元)'].resample('7D').max().plot()
# 'M','A','Q','W': right,在降采样时,各时间段的哪一段是闭合的
xx.dt.strftime() – 处理后的数据就不再是datetime类型
xx.dt.strftime(各种格式) :
xx.dt.strftime(’%y-%m-%d’)
xx.dt.strftime(’%y%m%d’)
xx.dt.year – 直接提取出年份–返回int64
xx.dt.month
xx.dt.day
xx.dt.time
xx.dt.hour
xx.dt.weekday – 星期一0,星期天6
df[‘日期一’]-df[‘日期二’] – 返回timedelta64[ns]
df[‘日期一’]-df[‘日期二’].dt.days – 返回Int
计算日期位于某一年的第几天:
df[‘日期一’].dt.dayofyear – 返回int64
计算日期位于一年的第几周
df[‘日期一’].dt.weekofyear – int64
from sklearn.datasets import load_boston
# 加载波士顿房价数据
dataset = load_boston()
dir(dataset)
# ['DESCR', 'data', 'feature_names', 'filename', 'target']
# 显示数据的描述
print(dataset.DESCR)
# 特征的名字
dataset.feature_names
# array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'], #dtype='
# 创建DataFrame对象
df = pd.DataFrame(data=dataset.data, columns=dataset.feature_names)
df['PRICE'] = dataset.target
df
#CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT PRICE
#0 0.00632 18.0 2.31 0.0 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 396.90 4.98 24.0
#1 0.02731 0.0 7.07 0.0 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 396.90 9.14 21.6
# 计算皮尔逊相关系数
df.corr()
# 基于RM(平均房间数)来预测PRICE(房价)
x, y = df['RM'], df['PRICE']
history_data = list(zip(x, y))
import heapq
# k近邻算法(kNN - k Nearest Neighbors)
def predict_price_by_knn(history_data, rm, top_n=5):
# nearest_data = sorted(history_data, key=lambda x: (x[0] - rm) ** 2)[:top_n]
nearest_data = heapq.nsmallest(top_n, history_data, key=lambda x: (x[0] - rm) ** 2)
return np.mean([x[1] for x in nearest_data])
# 预测房价
predict_price_by_knn(history_data, 5.25)
# 12.1
predict_price_by_knn(history_data, 6.125)
# 22.119999
import random
best_a, best_b = None, None
best_mse = np.inf
# 蒙特卡洛模拟
for _ in range(1000):
a, b = random.randrange(-100, 101), random.randrange(-100, 101)
curr_mse = np.mean(((a * x + b) - y) ** 2)
if curr_mse < best_mse:
best_mse = curr_mse
best_a, best_b = a, b
print(best_a, best_b)
print(best_mse)
# 9 -33
#44.66433044861659
# 绘制拟合曲线
y_hat = 9 * x - 33
plt.scatter(x, y)
plt.plot(x, y_hat, color='red')
plt.show()
# 用回归模型进行预测
def find_price_by_regression(rm):
return 9 * rm - 33
# 预测
find_price_by_regression(5.25)
y ^ = a x + b \hat{y} = ax + b y^=ax+b
M S E = 1 N ∑ i = 1 N ( y i ^ − y i ) 2 MSE = \frac{1}{N} \sum_{i=1}^{N}(\hat{y_i} - y_i)^2 MSE=N1i=1∑N(yi^−yi)2
M S E = 1 N ∑ i = 1 N ( a x i + b − y i ) 2 MSE = \frac{1}{N} \sum_{i=1}^{N}(ax_i + b - y_i)^2 MSE=N1i=1∑N(axi+b−yi)2
# 求最小二乘解
param1 = np.stack((x, np.ones(x.size))).T
param2 = y
np.linalg.lstsq(param1, param2, rcond=None)
#(array([ 9.10210898, -34.67062078]),
# array([22061.87919621]),
# 2,
# array([143.99484122, 2.46656609]))
# 用最小二乘解的结果修正刚才回归模型
def find_price_by_regression(rm):
return 9.1021 * rm - 34.6706
find_price_by_regression(5.25)
# 13.1154...
matplotlib 是为 python 提供强大绘图功能的第三方库,它的配置文件即 .rc 文件,为 matplotlib 输出图形的几乎所有属性指定了永久的默认值。(图形属性包括包括窗体大小、每英寸的点数、线条宽度、颜色、样式、坐标轴、坐标和网络属性、文本、字体等)
通过参数字典rcParams可以访问并修改已经加载的配置项
# 使图表上的中文编码正常显示
# sans-serif:无衬线字体
# 字体详情看C:\Users\Administrator\.matplotlib\fontList.json
plt.rcParams['font.sans-serif']=['STFangsong','STZhongsong']
# 使坐标刻度正常显示正负号
plt.rcParams['axes.unicode_minus']=False
dpi:dot per inch svg 矢量图
# 设置图片的输出格式为svg,保证图片不糊
%config InlineBackend.figure_format='svg'
绘制画布(figsize)->定制刻度->定制位置->保存->显示
# 创建画布
plt.figure(figsize=(8,3),dpi=125)
# 创建坐标系
#创建两个图,目前是第一个图
plt.subplot(2,1,1)
# 指定坐标轴
x = np.linspace(-2*np.pi,2*np.pi,100) # 等差数列
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x,y1,color='red',marker=' ')
# 创建两个图,现在是第二个图
plt.subplot(2,1,2)
plt.plot(x,y2,color='red',marker=' ')
# 支持数学公式的显示
plt.xlabel(r'$ \alpha $')
plt.ylabel(r'$ \sqrt[3]{\frac{1}{sin(\gamma)}} $',rotation=0)
# 保存图片
plt.savefig('dome.svg')
# 显示
plt.show()
# 在图片显示的时候会释放,所以一定要先保存再显示
# 读取图片的三维数组
guido = plt.imread('guido.jpg')
guido.shape
# (750,500,3)
# 显示图片
plt.imshow(guido)
# 图片垂直翻转
plt.imshow(guido[::-1])
# 图片镜转
plt.imshow(guido[:, ::-1])
# 图片切割
plt.imshow(guido[30:350, 85:310])
# 图片旋转90
plt.imshow(guido.swapaxes(0, 1))
# 图片变色
plt.imshow(guido[:, :, ::-1])
# 图片马赛克
plt.imshow(guido[::12, ::12])
数据分析的一般性流程:
提取数据(筛选)
布尔索引
query()
:相当于布尔索引
drop()
:删除指定的行或列
df.drop(columns=['categories'], axis=1,inplace=True)
# axis : {0 or 'index', 1 or 'columns'}, default 0
# Whether to drop labels from the index (0 or 'index') or columns (1 or 'columns').
del df['categories']
rename()
:重命名行或列索引
reset_index()
:重置索引(将索引变成普通列)
set_index()
:设置索引(将一个列或多个列指定为索引)
reindex()
:调整行或列索引的顺序(还可以做花式索引)
整合和重塑
merge()
:实现两个DataFrame对象的内连接或外连接(适用于两张表有关联)。concat()
:将两个或多个DataFrame的数据拼接到一起(适用于多张表结构一致)。数据清洗(缺失值、重复值、异常值)
缺失值:
dropna()
:删除空值
fillna()
:填充空值 <— 均值、中位数、众数
isnull()
/ notnull()
:判断空值
# 检查数据中是否含有任何缺失值
df.isnull().values.any()
重复值:
duplicated()
:判断是否重复drop_duplicates()
:删除重复值异常值:
drop()
:删除replace()
:替换预处理:
apply()
:将函数作用到数据上,需要指定在哪个轴上执行transform()
:将(多个)函数作用到数据上applymap()
:对每个元素使用指定的函数进行映射,相当于Series
上的map()
方法 —> elementwise注意:这三个方法都是高阶函数的用法,
apply()
方法接受的函数,可以是带归约性质的函数(聚合函数),也可以是没有归约性质的函数。transform()
方法接受的函数不能是带归约功能的函数,只能是对数据做变换的函数,简单的说就是函数的执行不会减少数据的量。
数据透视(排序、分组、聚合)
groupby()
—> sum()
/ mean()
/ max()
/ …pivot_table()
—> 专门生成透视表的函数cut()
—> 数据离散化(分箱)数据可视化(统计图表)
plot()
—> 出统计图表
xticks()
:横坐标的刻度yticks()
:纵坐标的刻度xlabel()
:横轴的标签ylabel()
:纵轴的标签legend()
:图例grid()
:网格线text()
:在图上添加文字annotate()
:在图上添加标记布尔索引
- `query()`:相当于布尔索引
- `drop()`:删除指定的行或列
```python
df.drop(columns=['categories'], axis=1,inplace=True)
# axis : {0 or 'index', 1 or 'columns'}, default 0
# Whether to drop labels from the index (0 or 'index') or columns (1 or 'columns').
del df['categories']
```
- `rename()`:重命名行或列索引
- `reset_index()`:重置索引(将索引变成普通列)
- `set_index()`:设置索引(将一个列或多个列指定为索引)
- `reindex()`:调整行或列索引的顺序(还可以做花式索引)
整合和重塑
merge()
:实现两个DataFrame对象的内连接或外连接(适用于两张表有关联)。concat()
:将两个或多个DataFrame的数据拼接到一起(适用于多张表结构一致)。数据清洗(缺失值、重复值、异常值)
缺失值:
dropna()
:删除空值
fillna()
:填充空值 <— 均值、中位数、众数
isnull()
/ notnull()
:判断空值
# 检查数据中是否含有任何缺失值
df.isnull().values.any()
重复值:
duplicated()
:判断是否重复drop_duplicates()
:删除重复值异常值:
drop()
:删除replace()
:替换预处理:
apply()
:将函数作用到数据上,需要指定在哪个轴上执行transform()
:将(多个)函数作用到数据上applymap()
:对每个元素使用指定的函数进行映射,相当于Series
上的map()
方法 —> elementwise注意:这三个方法都是高阶函数的用法,
apply()
方法接受的函数,可以是带归约性质的函数(聚合函数),也可以是没有归约性质的函数。transform()
方法接受的函数不能是带归约功能的函数,只能是对数据做变换的函数,简单的说就是函数的执行不会减少数据的量。
数据透视(排序、分组、聚合)
groupby()
—> sum()
/ mean()
/ max()
/ …pivot_table()
—> 专门生成透视表的函数cut()
—> 数据离散化(分箱)数据可视化(统计图表)
plot()
—> 出统计图表
xticks()
:横坐标的刻度yticks()
:纵坐标的刻度xlabel()
:横轴的标签ylabel()
:纵轴的标签legend()
:图例grid()
:网格线text()
:在图上添加文字annotate()
:在图上添加标记数据的洞察(发现问题给出建议)—> 一般性的方法(数据思维)和经验的积累