目录
1.Numpy,是科学计算的核心
2.Pandas,是数据分析的标准
2.1 Pandas基础数据结构——Series
2.2 Pandas表格数据结构Dataframe
2.2.1基础统计函数
2.2.2基础数据处理——用得非常多
2.2.3分组统计——groupby()
2.2.4高阶处理——apply(),且节省时间效率高
涉及到的包有两种:
通常import numpy as np。
numpy中的基础数据结构是array(数组),数组也就是矩阵的意思。一位数组是行向量,二维数组是列向量/矩阵,三维数组是在时间轴上的二维数组,三维和高维的数组通常用的不多。
常用的代码有以下部分:
import numpy as np
# =========创建数组==========
a = np.array([[1,2,3],
[4,5,6]])
b = np.zeros((2,3))
c = np.ones((2,3))
# =========维度变化=========
print('数组的维度是:', a.shape) # 输出 (2, 3)
print('将二维数组转成一维数组', a.ravel()) # 输出 将二维数组转成一维数组 [1 2 3 4 5 6]
print('改变二维数组形状:2*3 -> 3*2 \n', a.reshape((3,2)))
# 输出
# 改变二维数组形状:2*3 -> 3*2
# [[1 2]
# [3 4]
# [5 6]]
print('将二维数组转成列向量:\n', a.reshape((-1,1)))
# 输出
# 将二维数组转成列向量:
# [[1]
# [2]
# [3]
# [4]
# [5]
# [6]]
还有切片,切片类似于按照index分,比较简单。
比如a[0:3,1:4]输出0 1 2行,2 3 4列。再比如a[:3,-4:]输出前三行,后4列。
还有生成各种随机分布的随机数。常用的:均匀分布
from numpy import random
# 在[0,1)内产生随机数,维度是3*2
random.random((3, 2))
# 输出 array([[0.37025075, 0.56119619],
# [0.50308317, 0.01376845],
# [0.77282662, 0.88264119]])
# 产生指定区间的随机整数,维度是3*2
random.randint(low=2, high=10, size=(3, 2))
# 输出 array([[9, 5],
# [2, 3],
# [5, 2]])
# 均匀分布
random.uniform(low=3, high=10, size=(3, 2))
# 输出 array([[5.67622216, 3.3771158 ],
# [6.16153886, 9.87403319],
# [3.8675989 , 3.83566629]])
同大部分的数据分析库一样,Pandas的核心也是Numpy,Pandas是在Numpy基础上封装了高级接口,使得Pandas能处理包括数值型,字符串,日期等多种数据类型,提供了统计分析函数、日期处理函数、表格数据整理等,可大大提高数据分析的效率。
包含两种,基础数据结构series——序列数据,类似于字典结构,包括索引(字典中的“键”)和值(字典中的“值”);以及更全面的dataframe——表格数据,可以看成一张表,每一列都是一个series,所以dataframe是由多个series组成,虽然这些series的索引相同(行数相同),但其名称(列名)不同。
引用时通常用import pandas as pd。
类似于字典结构,包括索引(字典中的“键”)和值(字典中的“值”)。
import pandas as pd
# series的索引
index = ['2019/3/23', '2019/3/24', '2019/3/25', '2019/3/26', '2019/3/27',
'2019/3/28', '2019/3/29', '2019/3/30', '2019/3/31', '2019/4/1',
'2019/4/2', '2019/4/3', '2019/4/4']
# series的值
value = [18, 20, 19, 20, 18, 15, 17, 19, 20, 15, 18, 15, 20]
# 创建series
# 如果不指定索引,会自动生成0,1,2,....这样的索引
s = pd.Series(data=value, index=index)
print(s)
# 输出
# 2019/3/23 18
# 2019/3/24 20
# 2019/3/25 19
# 2019/3/26 20
# ...
dataframe是数据分析的基础。dataframe本质就是一张表,比如一张excel就是一个dataframe。可以包含不同种数据结构。
两种创建方式,当然还可以直接从数据库中导入进来(实际中用的多)。
import pandas as pd
# 创建方式1:这里的索引是1,2,3。通过字典创建,字典中的键表示daTaframe的列名,值是对应的值
df = pd.DataFrame(data={
'学号': ['x1', 'x2', 'x3', 'x4', 'x5'],
'姓名': ['张三', '李四', '王五', '韩六', '赵七'],
'身高': [177, 151, 167, 175, 153],
'语文成绩': [92, 84, 80, 77, 87],
'学分': [1.5, 2.3, 3.2, 1.2, 1.8],
'日期': ['2019/3/23', '2019/3/24', '2019/3/25', '2019/3/26', '2019/3/27']
})
print(df)
# 输出
# 学号 姓名 身高 语文成绩 学分 日期
# 0 x1 张三 177 92 1.5 2019/3/23
# 1 x2 李四 151 84 2.3 2019/3/24
# 2 x3 王五 167 80 3.2 2019/3/25
# 3 x4 韩六 175 77 1.2 2019/3/26
# 4 x5 赵七 153 87 1.8 2019/3/27
# 创建方式2:通过嵌套的list创建,需要额外指定列名。这里的索引是1,2,3。
df = pd.DataFrame(data=[
['x1', '张三', 177, 92, 1.5, '2019/3/23'],
['x2', '李四', 151, 84, 2.3, '2019/3/24'],
['x3', '王五', 167, 80, 3.2, '2019/3/25'],
['x4', '韩六', 175, 77, 1.2, '2019/3/26'],
['x5', '赵七', 153, 87, 1.8, '2019/3/27']
],
columns=['学号', '姓名', '身高', '语文成绩', '学分', '日期']
)
print(df)
# 输出
# 学号 姓名 身高 语文成绩 学分 日期
# 0 x1 张三 177 92 1.5 2019/3/23
# 1 x2 李四 151 84 2.3 2019/3/24
# 2 x3 王五 167 80 3.2 2019/3/25
# 3 x4 韩六 175 77 1.2 2019/3/26
# 4 x5 赵七 153 87 1.8 2019/3/27
# 查看dataframe的维度
print('dataframe的维度是:', df.shape)
# 输出 (5, 6)
# 从dataframe中拆出一个series
# 即dataframe中的一列就是一个series
high = df['身高']
print(high)
# 输出
# 0 177
# 1 151
# 2 167
# 3 175
# 4 153
# Name: 身高, dtype: int64
# 最大值最小值
df['身高'].max() # 输出 177
df['身高'].min() # 输出 151
# 均值和标准差
df['身高'].mean() # 输出 164.6
df['身高'].std() # 输出 12.1161
# 分位数:90% 的分位数
df['身高'].quantile(q=0.9) # 输出 176.2
# 累计值
df['身高'].cumsum()
# 输出
# 0 177
# 1 328
# 2 495
# 3 670
# 4 823
# Name: 身高, dtype: int64
# 相关系数
df[['身高', '语文成绩']].corr(method='pearson')
# 输出
# 身高 语文成绩
# 身高 1.000000 -0.063232
# 语文成绩 -0.063232 1.000000
# 协方差
df[['身高', '语文成绩']].cov()
# 输出
# 身高 语文成绩
# 身高 146.8 -4.5
# 语文成绩 -4.5 34.5
数据清洗,如缺失值异常值处理等;删除重复记录,排序,列的重命名,添加,删除等等。
(1)重命名列名,rename函数
df = df.rename(columns={'语文成绩':'成绩'})
# 列名由语文成绩变为成绩
(2)添加列或删除列,各有两种方法
# 添加
df['新列名']=[1,2,3,4,5] #法1,前面为列名,后边为值
df['新列名']=df['成绩']*0.8 #法2,在原有列基础上生成
# 删除
df = df.drop(columns=['新列名2']) #法1,实际中用的多
del df['新列名'] #法2
(3)子集选择,loc读取的是索引;iloc读取的是行数,相当于重新命名索引为0,1,2,...
# 选择索引范围在[2,4]的数据,即第3到第5行,index是从0计的
df.loc[2:4]
# 选择第2到第4行
df.iloc[1:4]
# 选择身高>160且成绩>80的数据,只要"姓名","学分","日期"3列
df.loc[(df['身高']>160) & (df['成绩']>80), ["姓名","学分","日期"]]
(4)排序,根据某列或多列的值进行升序或降序排序
#根据成绩降序排序,ascending=True 表示升序,ascending=False 表示降序。inplace=True替换之前的dataframe,默认是升序
df.sort_values(by=['语文成绩'], ascending=True)
(5)缺失值处理,一般用fillna填充
#先将张三成绩替换成缺失值(numpy.NaN),然后填充为80分
df.loc[(df['姓名']=='张三'), '语文成绩']=np.NaN
df['语文成绩']=df['语文成绩'].fillna(80)
#均值填充
df['语文成绩']=df['语文成绩'].fillna(df['语文成绩'].mean())
(6)异常值处理
# 将大于“均值+2倍标准差”的认为是异常值,用“均值+2倍标准差”代替
abnormal =df['语文成绩'].mean() + 2*df['语文成绩'].std()
df.loc[df['语文成绩']>abnormal, '语文成绩'] = abnormal
(7)删除重复记录——用的也比较多
# 根据“姓名,学号”判断是否重复,若重复则删除重复记录,只保留一条记录
df = df.drop_duplicates(subset=['姓名','学号'])
分组统计使用groupby函数,参数as_index=False表示统计后返回DataFrame类型的结果,否则返回series类型的结果。
而且groupby还可以应用自定义的函数对分组子集进行统计。
# 按照班级和性别分组,统计每个分组的人数
df.groupby(by=['班级', '性别'], as_index=False)['学号'].count()
# 输出
# 班级 性别 学号
# 0 1班 男 3
# 1 2班 女 2
# 按照班级和性别分组,统计每个组的成绩平均分
df.groupby(by=['班级', '性别'], as_index=False)['语文成绩'].mean()
# 输出
# 班级 性别 语文成绩
# 0 1班 男 85.333333
# 1 2班 女 82.000000
# 按照班级和性别分组,统计每个组的成绩总分
df.groupby(by=['班级', '性别'], as_index=False)['语文成绩'].sum()
# 输出
# 班级 性别 语文成绩
# 0 1班 男 256
# 1 2班 女 164
# 按照班级分组,对组内学生按成绩排序
rank = df.groupby(by=['班级'], as_index=False)['语文成绩'].rank()
df['排名'] = rank # 将排名信息添加到原来的DataFrame中
# 输出
# 学号 班级 姓名 性别 身高 语文成绩 学分 日期 排名
# 0 x1 1班 张三 男 177 92 1.5 2019/3/23 3.0
# 1 x2 1班 李四 男 151 84 2.3 2019/3/24 2.0
# 2 x3 1班 王五 男 167 80 3.2 2019/3/25 1.0
# 3 x4 2班 韩六 女 175 77 1.2 2019/3/26 1.0
# 4 x5 2班 赵七 女 153 87 1.8 2019/3/27 2.0
# 对每个分组使用自定义函数
# agg 或 apply 函数
def myfunc(series):
return '最大值是:' + str(series.max())
df.groupby(by=['班级', '性别'], as_index=False)['语文成绩'].agg(myfunc)
# 班级 性别 语文成绩
# 0 1班 男 最大值是:92
# 1 2班 女 最大值是:87
df.groupby(by=['班级', '性别'], as_index=False)['语文成绩'].apply(myfunc)
# 班级 性别
# 1班 男 最大值是:92
# 2班 女 最大值是:87
apply()括号中放的是函数。且接收的是series类型。
# apply
# 对姓名这一列的每个元素添加字母'xm'
def myfunc(x):
return 'xm' + x
df['姓名'] = df['姓名'].apply(myfunc)
# 输出
# 学号 班级 姓名 性别 身高 语文成绩 学分 日期
# 0 x1 1班 xm张三 男 177 92 1.5 2019/3/23
# 1 x2 1班 xm李四 男 151 84 2.3 2019/3/24
# ......
# 对成绩这一列,如果成绩小于90分则改成90份
def myfunc(x):
if x < 90:
return 90
else:
return x
df['语文成绩'] = df['语文成绩'].apply(myfunc)
# 输出
# 学号 班级 姓名 性别 身高 语文成绩 学分 日期
# 0 x1 1班 张三 男 177 92 1.5 2019/3/23
# 1 x2 1班 李四 男 151 90 2.3 2019/3/24
# ......
# 分组应用apply
# 需要注意的是,myfunc接收的参数是pandas.Series类型
def myfunc(series):
return series.max()
# 计算每个班级语文成绩最高分
df.groupby(by=['班级'], as_index=False)['语文成绩'].apply(myfunc)
# 0 92
# 1 90
# dtype: int64