4.1 数据的描述分析
import pandas as pd
BSdata=pd.read_excel('./data/DaPy_data.xlsx','BSdata'); #BSdata #读取数据
BSdata.head(5)
BSdata.describe()
BSdata[['性别','开设', '软件']].describe()
4.1.1 计数据汇总分析
(1)频数:绝对数
T1=BSdata['性别'].value_counts()
T1
(2)频率:相对数
T1/sum(T1)*100
4.1.2 计量数据汇总分析
(1)均数(算术平均数)
#1#
X.mean()
#2#
X=BSdata.身高.mean()
X
#3#
X=BSdata['身高'].mean()
X
168.51923076923077
(2)中位数
BSdata.身高.median()
167.5
(3)极差
X = BSdata['身高']
R=X.max()-X.min()
R
32
(4)方差
X.var()
64.29374057315236
(5)标准差
X.std()
8.01833776871194
(6)四分位数间距(IQR)
X.quantile(0.75)-X.quantile(0.25)
11.0
(7)偏度
X.skew()
0.29880755120910174
(8)峰度
X.kurt()
-0.42072371559816935
4.1.3 汇总性统计量
#BSdata[['性别','开设','课程','软件']].describe() #计数数据统计
#自编计算基本统计量函数
def stats(x):
stat=[x.count(),x.mean(),x.std(),x.min(),x.quantile(.25),x.median(), x.quantile(.75),x.max(),x.skew(),x.kurt()]
stat=pd.Series(stat,index=['count','mean','std','Min', '25%','50%','75%', 'max','skew','kurt'])
return(stat)
stats(BSdata.身高)
stats(BSdata.支出)
4.2 数据的直观分析
4.2.1 常用的绘图函数
#绘制图形时,须作一些基本设置
%config InlineBackend.figure_format='retina' #提高图形显示的清晰度
4.2.1.1 计数数据统计图
X=['A','B','C','D','E','F','G']
Y=[1,4,7,3,2,5,6]
● 条图(bar)
import matplotlib.pyplot as plt #加载基本绘图包
plt.bar(X,Y)
● 饼图(pie)
plt.pie(Y,labels=X);
4.2.1.2 计量数据统计图
● 线图(plot)
plt.plot(X,Y)
● 直方图(hist)
plt.hist(BSdata.身高) #频数直方图 ,默认density=False
X=['154-157.2','157.2-160.4','160.4-163.6','163.6-166.8','166.8-170','170-173.2','173.2-176.4','176.4-179.6','179.6-182.8','182.8-186']
Y=[4,5,5,9,9,6,5,4,1,4]
plt.bar(X, Y)
plt.hist(BSdata.体重) #频率直方图 ,density=True
● 散点图(scatter)
plt.scatter(BSdata.身高, BSdata.体重);
4.2.1.3 图形参数的设置
(1)标题、标签、标尺及颜色
plt.plot(X,Y);
plt.plot(X,Y,c='red'); #控制图形的颜色colors,c='red' 为红色
plt.ylim(0,8);
plt.rcParams['font.sans-serif']=['SimHei']; #设置中文黑体
plt.xlabel('姓名'); plt.ylabel('取值'); #plt.xlabel、plt.ylabel:设置坐标轴名称;
(2)线型和符号
plt.plot(X,Y, linestyle=':', marker='o');
# linestyle:控制连线的线型(-: 实线,--: 虚线,.: 点线);
# marker:控制符号的类型,例如,'o' 绘制实心圆点图。
(3)绘图函数附加图形
plt.plot(X,Y,'o--');
plt.axvline(x=4); # 水平线:在横坐标x处画水平(plt.axhline)
plt.axhline(y=4); # 垂直线:在纵坐标y处画垂直线(plt.axvline)
(4)文字函数:text(x, y, labels,...),在(x, y)处添加用 labels 指定的文字
plt.plot(X,Y,'o--');
plt.axvline(x=4); # 水平线:在横坐标x处画水平(plt.axhline)
plt.axhline(y=4); # 垂直线:在纵坐标y处画垂直线(plt.axvline)
plt.text(2, 7, ' peak point');
(5)图例:绘制图形后,可使用 legend 函数给图形加图例
plt.plot(X,Y,'.', label='point'); plt.legend();
(6)误差线图
# s=[0.1,0.4,0.7,0.3,0.2,0.5,0.6] #误差值
# plt.plot(X,Y)
# plt.errorbar(X,Y,yerr=s,fmt='o',capsize=4);
import matplotlib.pyplot as plt
# 假设 X 和 Y 已经定义
X = range(10) # 示例 X 数据
Y = [i * 0.1 for i in range(10)] # 示例 Y 数据
s = [0.1, 0.4, 0.7, 0.3, 0.2, 0.5, 0.6] # 误差值
# 截断 Y 以匹配 s 的长度
Y_truncated = Y[:len(s)]
plt.plot(X[:len(s)], Y_truncated)
plt.errorbar(X[:len(s)], Y_truncated, yerr=s, fmt='o', capsize=4)
plt.show()
(7)误差条图
# plt.bar(X,Y,yerr=s,capsize=4); #kw={'capsize':4}
4.2.1.4 多图的排列与绘制
(1)一行绘制两个图形
plt.subplot(121)
plt.bar(X,Y);
plt.subplot(122)
plt.plot(Y);
(2)一列绘制两个图形
plt.subplot(231)
plt.bar(X,Y)
plt.subplot(232)
plt.plot(Y)
plt.subplot(233)
plt.subplot(234)
plt.subplot(235)
plt.subplot(236)
(3)根据页面大小绘制两个图形
fig,ax = plt.subplots(1,2,figsize=(12,6))
ax[0].bar(X,Y)
ax[1].plot(X,Y)
(4)一页绘制四个图形
fig,ax=plt.subplots(2,2,figsize=(12,8))
ax[0,0].bar(X,Y)
ax[0,1].pie(Y,labels=X)
ax[1,0].plot(Y);
ax[1,1].plot(Y,'.-',linewidth=3);
4.2.2 基于 pandas 的绘图
4.2.2.1 计量数据统计图
#BSdata.head()
import matplotlib.pyplot as plt
plt.plot(BSdata['体重'])
plt.rcParams['font.sans-serif']=['SimHei']; #设置中文黑体
BSdata['体重'].plot(kind='line') #线图
BSdata['体重'].plot(kind='hist'); #直方图
#stats(BSdata.体重)
BSdata['体重'].plot(kind='box'); #箱型图
BSdata[['身高','体重','支出']].plot(subplots=True,layout=(3,1),kind='box',figsize=(4,10))
#help(pd.DataFrame.plot)
BSdata[['身高','体重','支出']].plot(subplots=True,layout=(1,3),kind='density',figsize=(10,4));
BSdata[['身高','体重','支出']].plot(subplots=True,layout=(3,1),kind='density',figsize=(10,6));
4.2.2.2 计数数据统计图
T1=BSdata['开设'].value_counts()
T1
pd.DataFrame({'频数':T1,'频率':T1/T1.sum()*100})
T1.plot(kind='bar'); #T1.sort_values().plot(kind='bar');
T1.plot(kind='pie');
4.3 数据的分组分析
4.3.1 一维频数表与图
4.3.1.1 计数数据频数分布
(1)value_counts
BSdata['开设'].value_counts()
(2)自定义计数汇总函数
# def tab(x, plot=False): #计数频数表
# f=x.value_counts();f
# s=sum(f);
# p=round(f/s*100, 3); p
# T1=pd.concat([f,p], axis=1);
# T1.columns=['例数','构成比'];
# T2=pd.DataFrame({'例数':s,'构成比':100.00}, index=['合计'])
# Tab=T1.append(T2)
# if plot:
# fig,ax=plt.subplots(1,2,figsize=(10,4))
# ax[0].bar(f.index, f); #条图
# ax[1].pie(p, labels=p.index, autopct='%1.2f%%');#饼图
# return(round(Tab, 3))
import pandas as pd
import matplotlib.pyplot as plt
def tab(x, plot=False): # 计数频数表
f = x.value_counts()
s = sum(f)
p = round(f / s * 100, 3)
T1 = pd.concat([f, p], axis=1)
T1.columns = ['例数', '构成比']
T2 = pd.DataFrame({'例数': [s], '构成比': [100.00]}, index=['合计'])
Tab = pd.concat([T1, T2]) # 使用pd.concat来合并DataFrame
if plot:
fig, ax = plt.subplots(1, 2, figsize=(10, 4))
ax[0].bar(f.index, f) # 条图
ax[0].set_title('条形图')
ax[0].set_xlabel('类别')
ax[0].set_ylabel('例数')
ax[1].pie(p, labels=f.index, autopct='%1.2f%%') # 饼图
ax[1].set_title('饼图')
plt.tight_layout()
plt.show()
return Tab.round(3)
# 示例使用
# 假设BSdata是一个Pandas DataFrame,并且有一个名为'身高'的列
# tab(BSdata.身高, plot=True)
tab(BSdata.软件,True)
4.3.1.2 计量数据频数分布
(1)身高频数表与条图
H_cut=pd.cut(BSdata.身高, bins=5)
H_cut #身高分10组,bins=[150,160,170,180,190,200]
H_cut.value_counts() #分组再统计
H_cut.value_counts().plot(kind='bar'); #将结果画成垂直条图
BSdata.身高.hist();
(2)支出频数表
O_cut=pd.cut(BSdata.支出, bins=[0,10,30,100]); #O_cut
O_cut.value_counts()
O_cut.value_counts().plot(kind='bar');
(3)自定义计量频率分析函数
import numpy as np
def freq(X,bins=10): #计量数据的频数表与直方图
H=plt.hist(X,bins);
a=H[1][:-1]; b=H[1][1:]; f=H[0];
p=f/sum(f)*100;p
cp=np.cumsum(p);cp
Freq=pd.DataFrame([a,b,f,p,cp])
Freq.index=['[下限a','上限b)','频数f','频率p(%)','累计频数cp(%)']
return(round(Freq.T,2))
freq(BSdata.体重)
4.3.2 二维集聚表与图
4.3.2.1 计数数据的列联表
(1)二维列联表
#Pandas的crosstab()函数可以把双变量分类数据整理成二维表形式
pd.crosstab(BSdata.开设, BSdata.课程)
#Pandas的crosstab()函数可以把双变量分类数据整理成二维表形式
pd.crosstab(BSdata.课程, BSdata.开设)
pd.crosstab(BSdata.开设, BSdata.课程)
#行和列的合计可使用参数 margins=True
pd.crosstab(BSdata.开设, BSdata.课程, margins=True)
#normalize ='index'表示各数据占行的比例
pd.crosstab(BSdata.开设, BSdata.课程, margins=True, normalize='index')
pd.crosstab(BSdata.开设, BSdata.课程,margins=True)
#normalize ='columns'表示各数据占列的比例
pd.crosstab(BSdata.开设, BSdata.课程, margins=True, normalize='columns')
#normalize ='all',表示各数据占总和的构成比例
pd.crosstab(BSdata.开设, BSdata.课程, margins=True, normalize='all').round(2)
(2)复式条图
T2=pd.crosstab(BSdata.开设, BSdata.课程)
T2
T2.plot(kind='bar')
#stacked 参数设置为False时,作出的是分段式条形图;为True时,作出的是并列式条形图
T2.plot(kind='bar', stacked=False)
T2.plot(kind='bar', stacked=True)
4.3.2.2 计量数据的集聚表
分组 groupby 函数
# 按列分组
BSdata.groupby(['性别'])
type(BSdata.groupby(['性别'])) #使用 groupby()函数生成的是一个中间分组变量,为 GroupBy 类型
pandas.core.groupby.generic.DataFrameGroupBy
# 按分组统计
BSdata.groupby(['性别'])['身高'].mean()
import pandas as pd
BSdata=pd.read_excel('./data/DaPy_data.xlsx','BSdata'); #BSdata #读取数据
BSdata.head()
BSdata.groupby(['性别'])['身高'].size()
T1=BSdata['性别'].value_counts()
T1
BSdata.groupby(['性别','开设'])['身高'].mean()
# 聚集函数 agg()
BSdata.groupby(['性别'])['身高'].agg([np.mean, np.std])
# 应用函数 apply()
# BSdata.groupby(['性别'])['身高','体重'].apply(np.mean)
BSdata.groupby(['性别'])[['身高', '体重']].apply(np.mean)
BSdata.groupby(['性别','开设'])[['身高','体重']].apply(np.mean)
4.3.3 多维透视表与图
4.3.3.1 计数数据透视表与图
#pt11=BSdata.pivot_table(values=['学号'],index=['性别'],aggfunc=len)
pt11=BSdata.pivot_table(['学号'],['性别'],aggfunc=len)
pt11 #len分组长度
pt11.plot(kind='bar');
#pt12=BSdata.pivot_table(values=['学号'],index=['性别','开设'],aggfunc=len)
pt12=BSdata.pivot_table(['学号'],['性别','开设'],aggfunc=len);pt12
pt12.plot(kind='bar');
#pt13=BSdata.pivot_table(values=['学号'],index=['开设'],columns=['性别'],aggfunc=len);
pt13=BSdata.pivot_table(['学号'], ['开设'], ['性别'], aggfunc=len)
pt13
pt13.plot(kind='bar');
pt13.plot(kind='bar',stacked=True);
4.3.3.2 计量数据透视表与图
pt21=BSdata.pivot_table(index=['性别'], values=["身高"], aggfunc=np.mean);pt21
pt21.plot(kind='bar');
pt22=BSdata.pivot_table(index=['性别'], values=["身高"], aggfunc=[np.mean,np.std]);
pt22
pt22.iloc[:,0].plot(kind='bar',yerr=pt22.iloc[:,1]); #标准差条图
pt23=BSdata.pivot_table(index=["性别"], values=["身高","体重"]);pt23 # 默认计算均值
pt23.plot(kind='bar');
pt23.plot(kind='bar',subplots=True,layout=(1,2));
4.3.3.3 复合数据透视表与图
BSdata.pivot_table('学号', ['性别','开设'], '课程', aggfunc=len,
margins=True, margins_name='合计')
pt31=BSdata.pivot_table('学号',['性别','开设'],'课程',aggfunc=len)
pt31
pt31.plot(kind='bar',stacked=False);
pt32=BSdata.pivot_table(['身高','体重'],['性别',"开设"],aggfunc=[len,np.mean,np.std]);pt32
pt32.iloc[:,:2].plot(kind='bar');
pt32.iloc[:,2:4].plot(kind='bar');
pt32.iloc[:,4:6].plot(kind='bar');
pt32.iloc[:,2].plot(kind='bar', yerr=pt32.iloc[:,4]); #基于性别和开设的体重标准差条图