这节介绍如何使用pandas做简单的数据分析,内容包括基本统计分析、分组分析、分布分析、交叉分析(透视表)、结构分析和相关性分析
以下实例数据文件,可以从该站内链接获取
1.基本统计分析
一般统计某变量的最大最小值,中值,分位值,中位数,众数,均值等
size 计数
sum() 求合
mean() 均值
var() 方差
std() 标准差
mode() 众数
median() 中位数
2.分组分析
根据分组字段将分析对象划分为不同部分,以对比分析各组之间差异性的一种分析方法
说白了就是:计数,求合,平均值
df.groupby(by=['分类1','分类2',...])[被统计的列].agg({列名1:统计函数1,列名2:函数2,...})
import pandas as pd
import numpy as np
df1 = pd.read_csv("../material/i_nuc_sheet7.csv")
df1 = df1.iloc[:,1:]
print(df1.head())
print(df1.describe())
group = df1.groupby(['班级']) #第一参就是by参数
print(group['军训','英语','体育',"性别"].mean()) #性别不是数值,会被忽略
print(df1.groupby(['班级',"性别"])['军训','英语','体育',"性别"].mean()) #先对班分组,再对性别分组
#如果对科目获取不同的统计量,要用到agg()
res = df1.groupby(by=['班级','性别'])['军训',"英语"].agg({
"总分":np.sum,
"人数":np.size,
"均值":np.mean,
"方差":np.var,
"标准差":np.std,
"最高分":np.max,
"最低分":np.min
})
print(res)
3.分布分析
将数据进行等距或不等距的分组从而研究各组分布规律。
import pandas as pd
import numpy as np
df = pd.read_csv("../material/i_nuc_sheet7.csv")
df = df.iloc[:,1:]
df['总分']=df.iloc[:,4:].apply(lambda x:x.sum(),axis=1)
print(df)
bins = [df['总分'].min()-1,400,450,df['总分'].max()+1]
labels = ['400以下','400到450',"450及以上"]
df['等级'] = pd.cut(df['总分'],bins=bins,labels=labels)
#获取每个等级下的人数
level_num = df.groupby(by=['等级'])['总分'].agg({"人数":np.size})
print(level_num)
4.交叉分析(透视表)
交叉分析用于分析两个或两个以上分组变量间的关系,以交叉表形式进行变量关系的对比分析。
pivot_table(values,index,columns,aggfunc,fill_value)
values 数据透视表中的值
index 数据透视表的行
columns 数据透视表的列
aggfunc 统计函数
fill_value NAN的替换值
默认是对列进行透视
import pandas as pd
import numpy as np
df = pd.read_csv("../material/i_nuc_sheet7.csv")
df = df.iloc[:,1:]
print(df.pivot_table(index=['班级','姓名'])) #根据班级和姓名分组透视,透视所有列
print(df.pivot_table(['军训',"英语","体育","性别"],index=['班级',"姓名"])) #根据班级和姓名分组透视,透视军训,英语,体育列,性别由于是非数值,自动忽略
#如果希望再上面的透视表中看到性别一列,性别应该放到index中
print(df.pivot_table(['军训',"英语","体育"],index=['班级',"姓名","性别"]))
print(df.pivot_table(['军训',"英语","体育"],index=['班级',"性别","姓名"])) #姓名和性别换个位置,显示又不一样
#一般来说,index放可以作为分组的列名,像班级,性别,等级,分类这样
#column放数值类型的列
#一般使用value都会配合aggfunc对值进行处理
df['总分']=df.iloc[:,4:].apply(lambda x:x.sum(),axis=1)
bins = [df['总分'].min()-1,400,450,df['总分'].max()+1]
labels = ['400以下','400到450',"450及以上"]
df['等级'] = pd.cut(df['总分'],bins=bins,labels=labels)
print(df.pivot_table(
values=['总分'], #对总分字段根据等级这个分组获取人数和均值统计
index=['等级'],
aggfunc=[np.size,np.mean]
))
print(df.pivot_table(
values=['总分'],
index=['等级',"性别"],
aggfunc=[np.size,np.mean]
))
print(df.pivot_table(
values=['总分'],
index=['等级'],
columns=["性别"],
aggfunc=[np.size,np.mean]
))
#在最后两个print中,我们发现其实性别放在index还是column,它都会对性别进行分组,只不过,显示的形式不同,columns=["性别"]是将性别显示在列,index=['性别']是显示在行
5.结构分析
结构分析是在分组分析以及交叉分析的基础上,计算各组成部分所占比例,用于衡量总体内部特征的方法。
df_group.div(df_sum,axis=0)
axis 0是对列操作,1是对行操作
import pandas as pd
import numpy as np
df = pd.read_csv("../material/i_nuc_sheet7.csv")
df = df.iloc[:,1:]
df['总分'] = df.iloc[:,4:].apply(lambda x:x.sum(),axis=1)
print(df)
df_group1 = df.pivot_table(values=['总分'],index=['班级'],columns=['性别'],aggfunc=[np.sum])
print(df_group1)
# sum
# 总分
# 性别 女 男
# 班级
# 23080242 777 1562
# 23080243 1209 1270
# 23080244 827 2620
print(df_group1.sum()) #默认对列操作
# 性别
# sum 总分 女 2813
# 男 5452
print(df_group1.sum(axis=1)) #axis=1是对行操作
# 班级
# 23080242 2339
# 23080243 2479
# 23080244 3447
#按列获取占比,即每个班男生女生的各自总分数占自己班所有人的总分数之比
print(df_group1.div(df_group1.sum(axis=1),axis=0)) #第一参是一个series,axis=0表示,df_group1的第一列除以第一参整列,第二列除以第一参的series的整列...
#每个班的女生占三个班的女生分数之比
print(df_group1.div(df_group1.sum(axis=0),axis=1)) #df_group1的第一行除以第一参整列,第二行除以第一参的series的整列...
6.相关分析
判断两个变量是否具有线性相关关系;
pearson相关系数:用于分析两个连续变量间的关系,要求连续变量的取值服从正态分布
spearman秩相关系数用于描述不服从正态分布的变量,分类或者等级变量间的关联性
相关系数
0<= |r| <0.3 低度相关
0.3<= |r| <0.8 中度相关
0.8<= |r| <=1 高度相关
df.corr() #计算每列两两之间的相关度,返回df
Series.corr(other) #计算该序列和传入的序列间相关性,返回数值型
import pandas as pd
import numpy as np
df = pd.read_csv("../material/i_nuc_sheet7.csv")
df = df.iloc[:,1:]
df['总分'] = df.iloc[:,4:].apply(lambda x:x.sum(),axis=1)
#计算高代和数分的相关性
print(df['数分'].corr(df['高代']))
print(df['高代'].corr(df['数分'])) #两个结果一样
print(df.loc[:,["英语","体育","军训","解几","数分","高代"]].corr())
import pandas as pd
import numpy as np
df = pd.read_csv("../material/i_nuc_sheet1.csv")
print(df)
print(df.corr())
print(df.corr()['鼠标'])