一、安装与基本使用
进入jupyter
# 生成一个array
import array
arr = array.array()
但是,array仍然仅仅为一个集合,并不能做向量或矩阵的计算。因此需要使用numpy。
numpy中的ndarray
import numpy as np
nparr = np.array(range(10))
nparr.dtype # 利用dtype 查看数据类型
在计算中如果需要浮点数,可以在初始化时使用带有浮点的初始值
nparr1 = np.array([1, 2, 3.0])
nparr1.dtype
# 也可以在初始化时直接使用dtype指定数据类型
nparr2= np.array(list(range(5)), dtype=float)
nparr2.dtype
正常情况下,numpy可以自动选择数据类型。
numpy 的简单使用与性能测试
import numpy as np
def numpy_test(n):
a = np.arange(n) ** 2
b = np.arange(n) ** 3
c = a + b
return c
numpy_test(10)
%timeit numpy_test(10000000)
二、numpy中的矩阵和随机数生成
-
np.arange
np.arange(初始值,结束值,间隔) # 共计可以传入3个参数
-
np.linspace
生成等差数列
np.linspace(初始值, 结束值, 截取数据点数)
np.linspace(0, 20, 11)
# 若不包含20,可以使用
np.linspace(0, 20, 11, endpoint=False)
-
np.zeros
#用于创建零数组 np.zeros(10) # 默认为浮点数 np.zeros((行数,列数)) # 传入一个元组 np.zeros(shape(行数,列数),dtype=int)
-
np.ones
-
np.full
利用一个元素去填充矩阵
np.full((3, 5), 0.99)
np.full((3, 5), fill_value=0.99)
-
np.random
生成随机数
np.random.randint(0, 10)
np.random.randint(0, 10, size=5) # 生成5个随机数
np.random.randint(0, 10, size=(2,5)) # 生成2行5列的随机数
计算机生成的随机数均为伪随机数。随机数的生成依赖随机种子。为了获取相同的随机结果,可以在每次生成随机数前,设置随机数的种子。
np.random.seed(100)
np.random.randint(0, 10, 3)
np.random.random((元组)) # 生成X行X列浮点数
np.random.normal(均值, 标准差, size=(元组))
二、ndarray基础操作
-
数组维度
使用ndim,shape,size来查看
a = np.arange(10)
a.ndim # 查看维度
a.shape # 查看属性
a.size #
利用reshape来改变
a = np.arange(10)
a.reshape(行数,列数) # a变成了2行5列的数组
a.reshape(行数,-1) # 使用-1时numpy会自动计算列数
-
数组切片
a = np.arange(15) X = a.reshape(3, -1) X[1, 2] # 获取第2行第3列的数字
数组切片的使用
a[0:8:2] # 以间隔2取值
二维数组的操作
X[0:2, 0:3] # 取出前2行前3列的数组
X[:2, 0::2] # 在前2行中间隔1列进行取值
X[::-1, ::-1] # 取出所有行列,但行列顺序进行颠倒
切片所获取的新变量与原变量之间有引用关系
python列表切片所获取的新变量与原变量之间没有关系,而numpy中数组则有引用关系
a = np.arange(15)
x = a.reshape(3, -1)
x2 = x[::2, ::2]
x2[0, 0] = 99
如若需要新变量脱离与原变量的引用关系,则需要调用copy()方法
x3 = x[:2, :2].copy()
三、数组的合并与分割
-
np.concatenate
合并两个数组# 一维数组的合并 a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) c = np.concatenate([a, b]) # 二维数组的合并行 A = np.arange(6).reshape(-1, 3) B = np.arange(6, 18).reshape(-1, 3) C = np.concatenate([A, B]) # 二维数组进行合并列 D = np.concatenate([a, b], axis=1) # E = np.concatenate(d, F)
-
np.vstack
一维数组与二维数组在垂直方向作堆叠np.stack([A, a])
-
np.hstack
一维数组与二维数组在水平方向作堆叠时,要将一维数组利用reshape转化为二维数组a = a.reshape(-1, 1)
-
np.split
# 一维数组的分割 a = np.array(range(10)) b = np.split(x, 2) c1, c2, c3 = np.split(x, [3,7]) # 3和7为分割点 # 二维数组的分割 A = np.arange(16).reshape(-1, 4) b1, b2 = np.split(A, [3]) # b1 = array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) # b2 = array([[12, 13, 14, 15]]) c1, c2= np.splite(A, [3], axis=1) # c2 = array([[ 3], [ 7], [11], [15]])
np.vsplit
-
np.hsplit
# 将最后一列拆分出来 c1, c2 = np.split(A, [-1])
四、矩阵运算
加减乘除
np.abs()
np.sin()
np.cos()
np.tan()
np.exp() # 以e为底
np.power(3, x) # 以3为底
np.log10(X)
矩阵与矩阵的运算
a = np.arange(4).reshape(2, -1)
b = np.full((2, 2), 10)
numpy中的加减乘除都是对应元素作相应运算。
要做标准矩阵的乘法运算,可以使用dot()
a.dot(b)
矩阵的逆
A = np.arange(4).reshape(2, -1)
invA = np.linalg.inv(A)
矩阵的转置
A.T
五、聚合操作
np.sum(X)
np.min(X)
对于二维数组求和时,
np.sum(X, axis=0) # 求垂直一列上的和
np.sum(X, axis=1) # 求水平一行上的和
np.prod(X) # 所有数相乘
np.mean(X, axis=)
np.median(X)
np.percentile(X, q=50)
np.var(X) # 求方差
np.std(X) # 求标准差
numpy中的arg运算
argmin
argmax
-
np.argwhere
ind = np.argwhere(x > 0.5) x[ind]
np.random.shuffle(x)
将数组顺序打乱-
np.argsort()
ind = np.argsort(x) #二维数组可以通过np.argsort(x, axis=0或1)来进行方向上的排序 x[ind[:3]]
-
argpartition
- np.argpartition(x, 4) # 找到比4大和比4小的所有数,左右分开放
七、numpy中的比较运算
-
1. fancy indexing
ind = [1, 2, 4] ind = array([[1, 2], [3, 4]]) #生成二维数组
对于二维数组
row = [0, 2, 4]
col = [1, 3, 4]
x[row, col]
x[1:3, col]
-
2. 比较运算
np.all() np.sum((x >2) & (x < 10)) # 这里只能使用一个位运算符&,不能使用2个。 np.sum((x >2) | (x < 10)) # np.sum(~(x == 2)) # 找到不等于2的值的个数
提取第2行中能被2整除的列
y = np.arange(16).reshape(4, -1)
ind = y[1, :] % 2 == 0
y[:, ind]
八、pandas的安装与数据结构
安装
-
Series
ser = np.Series(<data>, index=[1, 4]) ser.values
Series可以将字典中的key自动作为索引,也可以将series转为字典或列表
data = {'beijing': 10000, 'shanghai': 9999}
ser = pd.Series(data, index=['shanghai', 'Shenzhen'])
ser.to_dict() # 将ser转化为字典
ser.to_list() # key会被丢掉
ser.to_json()
ser.to_frame()
-
DataFrame
data = np.arange(100, 109).reshape(3, -1) df = pd.DataFrame(data, columns=['金额', '数量', 'fff'])
九、pandas对数据的选取操作
data = {
'name': ['张三', '李四', '钱二', '孙六'],
'age': [20, 24, 25, 23],
'height': [168, 179, 164, 170],
}
df = pd.DataFrame(data, columns=['name', 'age', 'height'])
df['name']
df.age
df[['age', 'name']]
names = df.name
names[1] = '周七' # 此时原数据data也被修改
ages = df.age.copy()
ages[2] = 28 # 此时原数据data不会被修改
ind = df.columns[1:2]
df[ind] #获取第2列数据
通过以上数据计算出生年份
import datetime
df['year'] = datetime.datetime.now().year - df.age
df
删除列
df.drop('year', axis=1)
df.drop(df.columns[2:3], axis=1)
以行的角度截取数据,返回的是Series
df.loc[2] # 获取第3行所有数据
如果要返回dataframe格式的数据,则需要使用列表
df.loc[[1, 3]] # 这里的1到3指的是index中的行名称,而不是第几行。如果中间有缺失就会报错
可以使用整数获取行,要仔细区别loc[]和iloc[]的区别
df.iloc[2] # 获取第3行的数据,可以不受index限制
df.iat[1, 1] # 获取第2行第列中的数据
df.index # 默认为整数序列
ind = df.index[-2:]
df.loc[ind2] # 等同于df[-2:] ; # 不加冒号等同于取列
增加一行数据
df.shape
df.loc[df.shape[0]] = {'name': '吴十一', 'age': 29, 'height': 172, 'year': 1989}
删除行
df.drop()
筛选数据
ind5 = df.height >= 170
ind6 = df.age > 25
df[ind5]
df[(ind5) & (ind6)]
df.query('height>=170 and age>25')
df.query('height>=170 and age>25 or name=="吴十一"')
# query同时支持变量查询
age = 27
df.query('age >= @age')
# 指定搜索
df[df.age.isin([19, 25])]
十、pandas加载数据
-
text
pd.read_table('<path>/<filename>.txt')
很多情况下一行包含多个信息,如果使用read_table正确加载,需要标题之间不使用空格,而是tab。
可以手动指定分隔符
pd.read_table('<path>/<filename>.txt', sep=':', header=None) # 同时指定没有标题行
pd.read_table('<path>/<filename>.txt', sep=':', names=['ID', 'info'], parse_dates = ['created_at']) # 如果含有时间序列,则需要指定解析某一列为时间
-
csv
pd.read_csv('<filename>.csv')
-
Excel
首先需要 pip install xlrdpd.read_excel('<filename>.xlsx')
-
html
tables = pd.read_html('<filename>.html', header=0) # 当页面表格中有标题行时,要设置header=0 table[0] # 使用索引可以解决页面中含有多个table的情况
也可以通过指定表格属性
pd.read_html('<filename>.html', header=0, attrs={'class': 'mydata'})
-
MySQL
import pymysql connection = pymysql.connect(host='', user='', password='', db='', charset='utf8') sql = 'select * from tableName' data = pd.read_sql(sql, connection) connection.close()
-
MongoDB
import pymongo client = pymongo.MongoClient(host='', port=27017) db = '' table = '' cursor = client[db][table].find() data = pd.DataFrame(list(cursor) )
十、Pandas合并与排序
-
sort
import pandas as pd ser = pd.Series(list('CAB'), index=[2, 1, 3]) # 按照索引排序 ser.sort_index() # 升序排列 ser.sort_index(ascending=False) # 降序排列 # 按照值排序 ser.sort_values() # 升序排列 ser.sort_values(ascending=False) # 降序排列
应当注意,当使用values排序时,None永远排在最后。
二维数组排序
arr = [[9 ,4, 8],
[4, 6, 7],
[4, 5, 3]]
df= pd.DataFrame(arr, index=[0, 2, 1], columns=list('cab'))
df.sort_index() # 按照索引排序
df.sort_index(axis=1) # 按照列排序(需要指定轴)
-
rank
返回排名情况,这里应当区分sort和rank的区别,sort给出的是排序后的结果,而rank给出的是排序后的名次。这个方法与numpy中的arg运算或者pandas中的数据筛选类似。
十一、Pandas的数据汇总
data = [[1, None, ],
[4, 5],
[None, None],
[8, 9],
[7, 3],
[2, 9],]
df = pd.DataFrame(data, columns=['a', 'b'])
df.head # 显示前5行
df.head(2) # 显示前2行
df.tail(3) # 显示后3行
df.info() # 查看当前dataframe的基本信息
df.describe() # 显示数据的多项信息,包括数量、平均值、方差、四分位数等
df.sum()
df.a.sum() # a列求和
df.cusum() # 累加求和,显示一行与前面所有行的值的总和
df.count()
df.var() # 求方差
十二、 pandas中的数据分组与透视表
-
groupby
import pandas as pd df = pd.read_excel('./x1.xlsx') grouped = df.groupby('类别') # 按照类别对数据进行分类 grouped[['数量', '金额']].sum() # 对数量和金额两列进行求和 # 为了了解统一类别下不同商品的单价,可以使用类别和名称进行分组 goruped1 = df.groupby(['类别', '名称']) goruped1['单价'].max() # 对数据分组后,可以通过遍历查看每一个组的信息 for name, data in df.groupby('类别'): print(name) # 输出类别名称 print(data) # 输出该类别下所有信息
-
pivot_table 数据透视表
每一列显示的数据类型不同,如单价显示平均值,而数量显示总和
# 默认条件下pivot_table均是求平均值
z = df.pivot_table(index=['类别', '名称'], values=['单价', '数量'])
# 如若需要对数量求和,则
z = df.pivot_table(index=['类别', '名称'], values=['单价', '数量'])
十三、pandas中的时间序列
-
python中时间使用的复习
import time, timedelta z = time.time() # 从1970年到现在的秒数 localtime = time.localtime(z) # 获得结构化的时间 # 利用已知时间生成时间戳 time.strptime('2018-5-10 9:23:2', '%Y-%m-%d %H:%M:%S') from datetime import datetime now = datetime.now() now.year, now.second ......
-
pandas 中data_range的使用
在data_range中,默认(M)为月,W为周,Q为季度,H为小时,T为分钟,S为秒,D为天,A为年
pd.data_range('2018-10-1', '2018-10-31', freq='w') # 生成时间序列
pd.data_range('2018-10-1', freq='Q', peridos=10) # 以季度为周期,返回10个季度的时间间隔
-
pandas 中set_index的使用
data = {'time': pd.date_range('2018-10-6', periods=1000000, freq='T'), 'cpu': np.random.randn(1000000) + 20} df = pd.DataFrame(data, columns=['time', 'cpu'])
要取出某一时间段内的数据,则
df[(df.time>='2018-11-10 10:00:00') & df.time<='2018-11-13 23:00:00']
需要增大采样时间间隔,则先利用set_index将时间作为索引
df.set_index('time')
这时就可以利用切片获取时间
df2['2018-11-10 10:00:00':'2018-11-13 23:00:00']
也可以直接给定一个日期,获取该天内所有监控数据
df2['2018-11-9']
也可以利用groupby进行分组
df2.groupby(df2.index.date).mean() # 获取每天的平均值
df2.groupby(df2.index.hour).mean() # 获取每小时的平均值
-
pandas 中resample的使用
在上述例子中,原始数据为每隔1min取样,利用resample可以改变采样间隔
df2.resample('90S').mean() #每间隔90s进行采样,取平均值、最大值、最小值取决于实际需要
十四、pandas中的时间序列
本节主要讲matplotlib的使用,但我更喜欢pyecharts,所以相关的学习在官网手册中开展。
http://pyecharts.org/#/
十五、数据质量和特征分析及数据清洗
在爬虫等数据获取过程中,要考虑样本的数量或质量是否满足要求,样本之间有无关联性。探索性数据分析包括数据质量分析和数据特征分析
-
数据质量分析
检查是否存在脏数据
1. 缺失值
df.isnull() # 当数据为空(NaN)时,显示True
df.isnull().sum() # 数据为空的个数
2. 异常值
df.describe()
(df['年龄']>=16) | (df['年龄']<=30) # 可以通过对年龄段的筛选来获取异常值,异常值显示为False
3. 重复值
df.duplicated() # 只当两条数据全部一样时,才会返回True
df.duplicated(subset=['姓名']) # 当姓名一致时,才会返回True
4. 一致性
在实际分析过程中,可能会存在数据更新后结果不一致,叫法或写法不同的现象,都需要对数据做进一步的处理。
df['语言'].unique()
-
数据特征分析
1.分布分析
2. 对比分析
3. 周期分析
4. 贡献度分析
5. 相关性分析
import seaborn as sns
corr = df.corr()
sns.heatmap(corr)
plt.show()
-
数据清洗
1. 缺失值处理
df.dropna() # 默认有1个数据为空,则本条数据被丢弃
可以指定丢弃数据方式
df.dropna(how='all') # 当所有数据为空时,本条数据才会被丢弃
也可以针对某一列进行数据丢弃
df.dropna(subset=['salary']) # 本列中数据为空的数据会被丢弃
当数据缺失较多时,应当做填充处理
df.fillna(values)
不同的列可以填充不同的值,可以
df.fillna({'age':18, 'language':'nothing'})
pandas中有更高级的填充方式
df.fillna(method='ffill') # ffill 表示将前面一个样本的值赋给该样本 frontfill
df.fillna(method='bfill') # bfill 表示将前面一个样本的值赋给该样本 backfill
df.fillna(method='ffill') # ffill 表示将前面一个样本的值赋给该样本 frontfill
也可以使用差值函数
df.interpolate()
对于不是数值型的数据,大多数情况下使用固定值来进行标注
df.fillna({'language': 'missing'})
df.fillna({'language': 'missing'}, limit=2) # 加上limit可以限定填充个数
2. 异常值处理
获取上下四分位数,然后获取上下四分位数的间距range
q_upper = df.age.quantile(0.75)
q_lower = df.age.quantile(0.25)
range = q_upper - q_lower
设置一个系数,一般取1.5~3
k = 1.5
然后获取上下四分位1.5倍间距以内的所有数值
ind = (df.age<=q_upper +k*range) & (df.age>=q_lower-k*range)
df2 = df[]
3. 重复值处理
最直接的方式是丢弃处理
df.drop_duplicates() # 默认所有字段全部相同时,方才删除重复值
也可以利用字段来删除
df.drop_duplicates(['age', 'salary'])