Python数据分析
本文是快速上手数据分析的几个常用框架的使用过程,而不是详细讲解各个框架的具体使用。通过本文你可以快速了解到框架的使用
- Anaconda(统一的环境、包管理)
- matplotlib(主要做数据可视化图表)
- numpy(科学计算库的基础库)
- pandas( 最强大、最灵活、可以支持任何语言的开源数据分析工具 )
Anaconda
-
预装了大量常用 Packages。
-
完全开源和免费。
-
额外的加速和优化是收费的,但对于学术用途,可以申请免费的 License。
- 对全平台和几乎所有Python版本支持。
- 包含了Jupyter Notebook
- 清华镜像地址https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/
Jupyter Notebook 是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果
-
编程时具有语法高亮、缩进、tab补全的功能。
-
可直接通过浏览器运行代码,同时在代码块下方展示运行结果。
-
以富媒体格式展示计算结果。富媒体格式包括:HTML,LaTeX,PNG,SVG等。
-
对代码编写说明文档或语句时,支持Markdown语法。
-
支持使用LaTeX编写数学性说明。
matplotlib
-
能将数据进行可视化,更直观的呈现
- 使数据更加客观、更具说服力
- Python 2D-绘图领域使用最广泛的套件
案列:根据案例大家可以去实现其他几种图形的展示
#!/usr/bin/python
# -*- coding: utf-8 -*-
# author : acker
# date : 2020/10/31
import matplotlib.pyplot as plt,matplotlib.font_manager as font_manager
import random
# 数据在x轴的位置,是一个可迭代对象
x = range(0,120)
# 数据在y轴的位置,是一个可迭代对象
y = [random.randint(20,37) for i in range(120)]
# 大小 像素
plt.figure(figsize=(20,8),dpi=88)
# 绘图 插入x和y,通过plot绘制图形
plt.plot(x,y)
# 设置x轴的刻度
# plt.xticks(range(2,12,2))
# 设置x轴上为字符串
_x = x
# 中文配置 黑体
plt.rcParams['font.sans-serif']=['SimHei']
_x_str = ['10时:{}分'.format(i) for i in range(60)] + ['11时:{}分'.format(i) for i in range(60)]
# 参数一:x轴的坐标位置 参数二:x轴的显示 rotation旋转角度
plt.xticks(list(_x[::10]),_x_str[::10],rotation = 270)
# _x_str = ['10:{}'.format(i) for i in range(60)] + ['11:{}'.format(i) for i in range(60)]
# plt.xticks(list(_x[::10]),_x_str[::10],rotation = 270) # rotation 旋转
# 设置y轴的刻度
# plt.yticks()
# 展示图像
plt.show()
numpy
- 一个强大的N维数组对象 ndarray
- 广播功能函数
- 整合 C/C++/Fortran 代码的工具
- 线性代数、傅里叶变换、随机数生成等功能
下面是具体的案列实现,包括了numpy大部分常规操作,可以让开发者快速了解到numpy的使用过程。
#!/usr/bin/python
# -*- coding: utf-8 -*-
# author : acker
# date : 2020/11/2
import numpy as np
# 创建一维数组的方式
print("创建数组的方式")
arrs_a = np.arange(1,7).astype(int)
# arrs_b = np.array(range(1,7),dtype=int)
# arrs_c = np.array([1,2,3,4,5,6],dtype=int)
print('arrs_a\n',arrs_a)
# 创建二维数组的方式
arrs_aa = np.array([np.arange(1,4),np.arange(4,7)])
# arrs_aa = np.array([[1,2,3],[4,5,6]])
print('arrs_aa\n',arrs_aa)
print('*'*100)
# 查看数组的形状
print('查看数组的形状')
print('arrs_a的维度是:',arrs_a.shape)
print('arrs_aa的维度是:',arrs_aa.shape)
# 修改数组的形状
print('修改数组的形状')
print('arrs_a修改后\n',arrs_a.reshape(2,3))
print('arrs_aa修改后\n',arrs_aa.reshape(6,))
print('flatten将数组转换为一维数组\n',arrs_aa.flatten())
print('*'*100)
print('广播机制')
# 广播机制
print('加减乘除法会广播到每一个元素上,例如+1\n',arrs_a+1)
# 两个数组对应的最后存储的元素个数要相同才可以进行相应操作
# 例如shape为(2,2)的数组与shape为(2,3)的数组因为最后维度存储的个数不同会导致广播机制不能传播
# 例如shape为(2,2,3)的数组与shape为(1,1,3)不管其是几维数组只要其最后存储的元素个数相同就可以进行广播
print('数组与数组间的加减乘除,必须要最后的维度相同才可以进行,例如\n',np.array([1,2,3])+arrs_aa)
print('多维数组的加减乘除,例如\n',np.array([[[1,1,1],[1,1,1]],[[2,2,2],[2,2,2]]])+np.array([[[2,2,2]]]))
print('*'*100)
print('轴的概念')
# numpy中可以理解为方向使用0,1,2数字来表示不同的维度,
# 一维数组只有0轴,相当于只有x轴的概念
print('一维数组x为6\n',np.arange(6))
# 二维数组只有0,1轴,相当于x、y轴的概念,0表示为行数,1表示为列数
print('二维数组x为2,y为3\n',np.array([np.arange(3),np.arange(3)]))
# 三维数组只有0,1,2轴,相当于z、x、y轴的概念,0表示为块数,1表示为行数,2表示列数
print('三维数组z为1,x为2,y为3\n',np.array([[np.arange(3),np.arange(3)]]))
print('*'*100)
print('数组的转置')
print('arrs_aa\n',arrs_aa)
print('arrs_aa.transpose()\n',arrs_aa.transpose())
print('arrs_aa.T\n',arrs_aa.T)
# 转置与交换轴的效果一样
print('arrs_aa.swapaxes(1,0)\n',arrs_aa.swapaxes(1,0))
print('*'*100)
print('numpy索引和切片')
# 取出操作与数组的操作基本相似,只是增加了对x,y两个轴的取值方式arrs_aa[:,:],
print('arrs_aa\n',arrs_aa)
print('取arrs_aa的一行数据\n',arrs_aa[0])
print('取arrs_aa的一列数据\n',arrs_aa[:,0])
print('取arrs_aa的第一行的第一和第二列数据\n',arrs_aa[0,0:2])
print('*'*100)
print('numpy中布尔索引')
print('arrs_aa\n',arrs_aa)
print(arrs_aa<2)
# 修改了元数据
_arrs_aa = arrs_aa.copy()
_arrs_aa[_arrs_aa<2]=0
# 没有修改元数据,重新构造一个新的数组返回
# arrs_temp = np.where(arrs_aa<2,0,10)
print(arrs_aa)
print('*'*100)
print('numpy中的nan和inf')
# nan(NAN,Nan):not a number表示不是一个数字
# 读取为float,如果丢失,就会出现nan。
# nan与nan的值是不等的。
# nan与任何值计算都为nan
# inf(-inf,inf):infinity,inf表示正无穷,-inf表示负无穷 如果有个数字除以0,例如:
# python中会将0表示为极小值,就会得出有个极大(小)值,就会导致程序报错出现inf
arrs_nan = np.arange(6).astype(float)
arrs_nan[1] = np.nan
print('arrs_nan\n',arrs_nan)
print('判断nan的个数',np.count_nonzero(arrs_nan!=arrs_nan))
print('判断是否为nan',np.isnan(arrs_nan))
print('*'*100)
print('numpy中常用统计函数')
print('arrs_aa\n',arrs_aa)
print('求和:',arrs_aa.sum() )
print('均值(受离群点的影响较大):',arrs_aa.mean() )
print('中值:',np.median(arrs_aa))
print('最大值',arrs_aa.max() )
print('最小值',arrs_aa.min() )
print('极值(即最大值和最小值只差):',np.ptp(arrs_aa) )
print('标准差',arrs_aa.std() )
print('*'*100)
print('numpy中数组的拼接')
print('arrs_a\n',arrs_a.reshape(2,3))
print('arrs_aa\n',arrs_aa)
print('竖直拼接np.vstack((t1,t2))]\n',np.vstack((arrs_a.reshape(2,3),arrs_aa)))
print('水平拼接np.hstack((t1,t2))]\n',np.hstack((arrs_a.reshape(2,3),arrs_aa)))
# 获取最大值最小值的位置
# np.argmax(t,axis=0)
# np.argmin(t,axis=1)
# 创建一个全0的数组: np.zeros((3,4))
# 创建一个全1的数组:np.ones((3,4))
# 创建一个对角线为1的正方形数组(方阵):np.eye(3)
print('numpy的注意点copy和view')
# a=b 完全不复制,a和b相互影响
# a = b[:],视图的操作,一种切片,会创建新的对象a,但是a的数据完全由b保管,他们两个的数据变化是一致的,
# a = b.copy(),复制,a和b互不影响
pandas
- 与 SQL 或 Excel 表类似的,含异构列的表格数据;
- 有序和无序(非固定频率)的时间序列数据;
- 带行列标签的矩阵数据,包括同构或异构型数据;
- 任意其它形式的观测、统计数据集, 数据转入 Pandas 数据结构时不必事先标记。
- 不改变原始的输入数据,而是复制数据,生成新的对象。
- 主要数据结构是 Series(一维数据)与 DataFrame(二维数据)
- 数据的基本操作
import pandas as pd
import numpy as np
print('pands对象的创建')
print('*'*100)
# Series对象本质上由两个数组构成,一个数组构成的键(index),一个数组构成的值(value)
arrs_a = pd.Series(np.arange(10),index=range(10))
print('arrs_a\n',arrs_a)
print('arrs_a的键(index)\n',arrs_a.index)
print('arrs_a的值(values)\n',arrs_a.values)
# 取值的方式 arrs_a[0:] arrs_a[1],arrs_a[[0,1]]
# DataFrame对象既有行索引又有列索引
# 行索引,表明不同行,横向索引,叫index,0轴,axis=0
# 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
# arrs_aa = pd.DataFrame(np.arange(9).reshape((3,3)),index=list('ABC'),columns=list('abc'))
dict_aa = {"name":['a','b'],'age':[12,13]}
arrs_aa = pd.DataFrame(dict_aa)
print('arrs_aa\n',arrs_aa)
# 查看总体数据的情况 info()
# arrs_aa.info()
# 取值方式
# head()默认是获取5行
print('获取前两行\n',arrs_aa.head(2))
# arrs_aa[] 可以选择单列,可以切片多行
print('获取单列\n',arrs_aa['name'])
print('获取多行\n',arrs_aa[0:3])
# 按标签选择 loc[[],[]] loc[0:,0:] loc[(),()] 第一个表示获取的行切片行名,第二表示获取的列切片列名
print(arrs_aa.loc[[0],['age','name']]) # 0 表示的是index不是下标位置
print(arrs_aa.loc[0:,('age','name')]) # 0 表示的是index不是下标位置
# 按位置选择 iloc[[],[]] iloc[0:,0:] iloc[(),()] 第一个表示获取的行切片位置,第二表示获取的列切片位置
print(arrs_aa.iloc[0:,1]) # 表示的下标位置
# 布尔索引
print(arrs_aa[arrs_aa.age > 12])
- 数据清洗
# data_csv.info()
# 数据的去重值
# subset : column label or sequence of labels, optional
# 用来指定特定的列,默认所有列
# keep : {‘first’, ‘last’, False}, default ‘first’
# 删除重复项并保留第一次出现的项
# inplace : boolean, default False
# 是直接在原来数据上修改还是保留一个副本
data_csv.drop_duplicates(inplace=True)
# 数据的规范化
# 将列表中的浮点数,减小精度对数据处理的干扰,故对数值进行标准化操作,保留五位小数;
data_csv["销售金额"] = data_csv["销售金额"].round(decimals=5)
# 将日期转化为datetime类型,将非法日期至空,最后使用去空值操作去除
data_csv["销售日期"] = pd.to_datetime(data_csv["销售日期"],format='%Y%m%d',errors='coerce')
# 数据的去空值
# how = 'any' 即去除所有的空值 axis=0,按行去除
data_csv = data_csv.dropna(axis=0,how='any')
- Pandas的eval()与query()函数
- eval()相当于增删改操作
import pandas as pd
import numpy as np
df_01 = pd.DataFrame(np.arange(9).reshape((3,3)),columns=list('abc'))
df_02 = pd.DataFrame(np.arange(9).reshape((3,3)),columns=list('abc'))
# 对于DataFrame对象的操作
# 支持算术运算、比较运算、Bitwise运算
rt_01 = df_01 + df_01
rt_02 = pd.eval('df_01 + df_02')
# 对于DataFrame对象属性和索引的操作
data = df_01.eval('d = a +b')
data = df_02.eval('d = a[1] + b[2]')
# eval()中引用 local变量
column_mean = df_01.mean(1)
df_01['a'] + column_mean
df_01.eval('a + @column_mean')
- query()相当于查询
# 根据每一列的值比较来筛选出合适的值
df[(df.a < 3) & (df.b < 4)]
df.query('a < 3 and b < 4')
# 引用local变量
# mean(0) 对每一列取均值 mean 对每一行取均值
column_mean = df.mean(1)
print(df[(df.a > column_mean) & (df.b > column_mean)])
print(df.query('a > @column_mean & b > @column_mean'))
实际使用中,传统方法和eval/query相差不是很明显,传统方法在较小的array上更快一些
使用eval/query的好处,主要是节省内存以及有时他们具有更简洁的语法形式