import pandas as pd
pd.set_option('display.max_rows', 10)
BSdata=pd.read_excel('DaPy_data.xlsx','BSdata'); BSdata #读取数据
学号 | 性别 | 身高 | 体重 | 支出 | 开设 | 课程 | 软件 | |
---|---|---|---|---|---|---|---|---|
0 | 1510248008 | 女 | 167 | 71 | 46.0 | 不清楚 | 都未学过 | No |
1 | 1510229019 | 男 | 171 | 68 | 10.4 | 有必要 | 概率统计 | Matlab |
2 | 1512108019 | 女 | 175 | 73 | 21.0 | 有必要 | 统计方法 | SPSS |
3 | 1512332010 | 男 | 169 | 74 | 4.9 | 有必要 | 编程技术 | Excel |
4 | 1512331015 | 男 | 154 | 55 | 25.9 | 有必要 | 都学习过 | Python |
... | ... | ... | ... | ... | ... | ... | ... | ... |
47 | 1538319004 | 男 | 175 | 68 | 44.4 | 不清楚 | 统计方法 | SAS |
48 | 1538254010 | 女 | 166 | 65 | 5.3 | 不清楚 | 编程技术 | Python |
49 | 1540294017 | 女 | 159 | 58 | 71.4 | 不清楚 | 都学习过 | SPSS |
50 | 1540365026 | 女 | 169 | 73 | 5.5 | 有必要 | 统计方法 | Excel |
51 | 1540388036 | 女 | 165 | 67 | 56.8 | 不必要 | 概率统计 | SAS |
52 rows × 8 columns
T1=BSdata['性别'].value_counts();T1
男 27 女 25 Name: 性别, dtype: int64
T1/sum(T1)*100
男 51.923077 女 48.076923 Name: 性别, dtype: float64
X=BSdata.身高;
X.mean()
168.51923076923077
X.median()
167.5
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
X.kurt()
-0.42072371559816935
BSdata.describe() #默认为计算计量数据的基本统计量
学号 | 身高 | 体重 | 支出 | |
---|---|---|---|---|
count | 5.200000e+01 | 52.000000 | 52.000000 | 52.000000 |
mean | 1.523270e+09 | 168.519231 | 68.500000 | 24.511538 |
std | 1.899525e+07 | 8.018338 | 7.711718 | 21.432060 |
min | 1.438120e+09 | 154.000000 | 50.000000 | 2.500000 |
25% | 1.520377e+09 | 163.000000 | 63.000000 | 9.500000 |
50% | 1.526685e+09 | 167.500000 | 68.500000 | 15.450000 |
75% | 1.532229e+09 | 174.000000 | 73.000000 | 35.600000 |
max | 1.540388e+09 | 186.000000 | 87.000000 | 85.600000 |
#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.身高)
count 52.000000 mean 168.519231 std 8.018338 Min 154.000000 25% 163.000000 50% 167.500000 75% 174.000000 max 186.000000 skew 0.298808 kurt -0.420724 dtype: float64
stats(BSdata.支出)
count 52.000000 mean 24.511538 std 21.432060 Min 2.500000 25% 9.500000 50% 15.450000 75% 35.600000 max 85.600000 skew 1.268351 kurt 0.673127 dtype: float64
#绘制图形时,须作一些基本设置
%config InlineBackend.figure_format='retina' #提高图形显示的清晰度
X=['A','B','C','D','E','F','G']
Y=[1,4,7,3,2,5,6]
import matplotlib.pyplot as plt #加载基本绘图包
plt.bar(X,Y);
plt.pie(Y,labels=X);
plt.plot(X,Y);
plt.hist(BSdata.身高) #频数直方图 ,默认density=False
(array([4., 5., 5., 9., 9., 6., 5., 4., 1., 4.]), array([154. , 157.2, 160.4, 163.6, 166.8, 170. , 173.2, 176.4, 179.6, 182.8, 186. ]), <BarContainer object of 10 artists>)
plt.hist(BSdata.体重) #频率直方图 ,density=True
(array([ 1., 3., 3., 7., 12., 12., 4., 6., 3., 1.]), array([50. , 53.7, 57.4, 61.1, 64.8, 68.5, 72.2, 75.9, 79.6, 83.3, 87. ]), <BarContainer object of 10 artists>)
plt.scatter(BSdata.身高, BSdata.体重);
标题、标签、标尺及颜色
plt.plot(X,Y); #控制图形的颜色colors,c='red' 为红色
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:设置坐标轴名称;
线型和符号
plt.plot(X,Y, linestyle=':', marker='o');
# linestyle:控制连线的线型(-: 实线,--: 虚线,.: 点线);
# marker:控制符号的类型,例如,'o' 绘制实心圆点图。
绘图函数附加图形
plt.plot(X,Y,'o--');
plt.axvline(x=4); # 水平线:在横坐标x处画水平(plt.axhline)
plt.axhline(y=4); # 垂直线:在纵坐标y处画垂直线(plt.axvline)
文字函数: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');
图例:绘制图形后,可使用 legend 函数给图形加图例
plt.plot(X,Y,'.', label='point'); plt.legend();
误差线图
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);
误差条图
plt.bar(X,Y,yerr=s,capsize=4); #kw={'capsize':4}
plt.subplot(121); plt.bar(X,Y);
plt.subplot(122); plt.plot(Y);
plt.subplot(211); plt.bar(X,Y);
plt.subplot(212); plt.plot(Y);
fig,ax = plt.subplots(1,2,figsize=(12,6))
ax[0].bar(X,Y); ax[1].plot(X,Y);
fig,ax=plt.subplots(2,2,figsize=(10,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);
plt.rcParams['font.sans-serif']=['SimHei']; #设置中文黑体
BSdata['体重'].plot(kind='line'); #线图
BSdata['体重'].plot(kind='hist'); #直方图
stats(BSdata.体重)
count 52.000000 mean 68.500000 std 7.711718 Min 50.000000 25% 63.000000 50% 68.500000 75% 73.000000 max 87.000000 skew 0.002935 kurt 0.045948 dtype: float64
BSdata['体重'].plot(kind='box'); #箱型图
BSdata['体重'].plot(kind='hist');
BSdata['体重'].plot(kind='density',title='Density');
BSdata[['身高','体重','支出']].plot(subplots=True,layout=(1,3),kind='box',figsize=(10,4));
BSdata[['身高','体重','支出']].plot(subplots=True,layout=(1,3),kind='density',figsize=(10,4));
BSdata[['身高','体重','支出']].plot(subplots=True,layout=(3,1),kind='density',figsize=(10,6));
C:\Users\Lenovo\anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py:238: RuntimeWarning: Glyph 8722 missing from current font. font.set_text(s, 0.0, flags=flags) C:\Users\Lenovo\anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py:201: RuntimeWarning: Glyph 8722 missing from current font. font.set_text(s, 0, flags=flags)
T1=BSdata['开设'].value_counts();T1
pd.DataFrame({'频数':T1,'频率':T1/T1.sum()*100})
频数 | 频率 | |
---|---|---|
有必要 | 29 | 55.769231 |
不清楚 | 12 | 23.076923 |
不必要 | 11 | 21.153846 |
T1.plot(kind='bar'); #T1.sort_values().plot(kind='bar');
T1.plot(kind='pie');
BSdata['开设'].value_counts()
有必要 29 不清楚 12 不必要 11 Name: 开设, dtype: int64
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))
tab(BSdata.软件,True)
例数 | 构成比 | |
---|---|---|
Excel | 15 | 28.846 |
SPSS | 9 | 17.308 |
R | 7 | 13.462 |
Python | 6 | 11.538 |
SAS | 6 | 11.538 |
Matlab | 5 | 9.615 |
No | 4 | 7.692 |
合计 | 52 | 100.000 |
H_cut=pd.cut(BSdata.身高, bins=10); H_cut #身高分10组,bins=[150,160,170,180,190,200]
0 (166.8, 170.0] 1 (170.0, 173.2] 2 (173.2, 176.4] 3 (166.8, 170.0] 4 (153.968, 157.2] ... 47 (173.2, 176.4] 48 (163.6, 166.8] 49 (157.2, 160.4] 50 (166.8, 170.0] 51 (163.6, 166.8] Name: 身高, Length: 52, dtype: category Categories (10, interval[float64, right]): [(153.968, 157.2] < (157.2, 160.4] < (160.4, 163.6] < (163.6, 166.8] ... (173.2, 176.4] < (176.4, 179.6] < (179.6, 182.8] < (182.8, 186.0]]
H_cut.value_counts() #分组再统计
(166.8, 170.0] 10 (163.6, 166.8] 9 (157.2, 160.4] 5 (160.4, 163.6] 5 (170.0, 173.2] 5 (173.2, 176.4] 5 (153.968, 157.2] 4 (176.4, 179.6] 4 (182.8, 186.0] 4 (179.6, 182.8] 1 Name: 身高, dtype: int64
H_cut.value_counts().plot(kind='bar'); #将结果画成垂直条图
BSdata.身高.hist();
O_cut=pd.cut(BSdata.支出, bins=[0,10,30,100]); #O_cut
O_cut.value_counts()
(10, 30] 21 (0, 10] 16 (30, 100] 15 Name: 支出, dtype: int64
O_cut.value_counts().plot(kind='bar');
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.体重)
[下限a | 上限b) | 频数f | 频率p(%) | 累计频数cp(%) | |
---|---|---|---|---|---|
0 | 50.0 | 53.7 | 1.0 | 1.92 | 1.92 |
1 | 53.7 | 57.4 | 3.0 | 5.77 | 7.69 |
2 | 57.4 | 61.1 | 3.0 | 5.77 | 13.46 |
3 | 61.1 | 64.8 | 7.0 | 13.46 | 26.92 |
4 | 64.8 | 68.5 | 12.0 | 23.08 | 50.00 |
5 | 68.5 | 72.2 | 12.0 | 23.08 | 73.08 |
6 | 72.2 | 75.9 | 4.0 | 7.69 | 80.77 |
7 | 75.9 | 79.6 | 6.0 | 11.54 | 92.31 |
8 | 79.6 | 83.3 | 3.0 | 5.77 | 98.08 |
9 | 83.3 | 87.0 | 1.0 | 1.92 | 100.00 |
#Pandas的crosstab()函数可以把双变量分类数据整理成二维表形式
pd.crosstab(BSdata.开设, BSdata.课程)
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 |
---|---|---|---|---|---|
开设 | |||||
不必要 | 3 | 2 | 1 | 1 | 4 |
不清楚 | 3 | 3 | 3 | 2 | 1 |
有必要 | 5 | 10 | 6 | 7 | 1 |
#行和列的合计可使用参数 margins=True
pd.crosstab(BSdata.开设, BSdata.课程, margins=True)
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 | All |
---|---|---|---|---|---|---|
开设 | ||||||
不必要 | 3 | 2 | 1 | 1 | 4 | 11 |
不清楚 | 3 | 3 | 3 | 2 | 1 | 12 |
有必要 | 5 | 10 | 6 | 7 | 1 | 29 |
All | 11 | 15 | 10 | 10 | 6 | 52 |
#normalize ='index'表示各数据占行的比例
pd.crosstab(BSdata.开设, BSdata.课程, margins=True, normalize='index')
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 |
---|---|---|---|---|---|
开设 | |||||
不必要 | 0.272727 | 0.181818 | 0.090909 | 0.090909 | 0.363636 |
不清楚 | 0.250000 | 0.250000 | 0.250000 | 0.166667 | 0.083333 |
有必要 | 0.172414 | 0.344828 | 0.206897 | 0.241379 | 0.034483 |
All | 0.211538 | 0.288462 | 0.192308 | 0.192308 | 0.115385 |
#normalize ='columns'表示各数据占列的比例
pd.crosstab(BSdata.开设, BSdata.课程, margins=True, normalize='columns')
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 | All |
---|---|---|---|---|---|---|
开设 | ||||||
不必要 | 0.272727 | 0.133333 | 0.1 | 0.1 | 0.666667 | 0.211538 |
不清楚 | 0.272727 | 0.200000 | 0.3 | 0.2 | 0.166667 | 0.230769 |
有必要 | 0.454545 | 0.666667 | 0.6 | 0.7 | 0.166667 | 0.557692 |
#normalize ='all',表示各数据占总和的构成比例
pd.crosstab(BSdata.开设, BSdata.课程, margins=True, normalize='all').round(2)
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 | All |
---|---|---|---|---|---|---|
开设 | ||||||
不必要 | 0.06 | 0.04 | 0.02 | 0.02 | 0.08 | 0.21 |
不清楚 | 0.06 | 0.06 | 0.06 | 0.04 | 0.02 | 0.23 |
有必要 | 0.10 | 0.19 | 0.12 | 0.13 | 0.02 | 0.56 |
All | 0.21 | 0.29 | 0.19 | 0.19 | 0.12 | 1.00 |
T2=pd.crosstab(BSdata.开设, BSdata.课程);T2
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 |
---|---|---|---|---|---|
开设 | |||||
不必要 | 3 | 2 | 1 | 1 | 4 |
不清楚 | 3 | 3 | 3 | 2 | 1 |
有必要 | 5 | 10 | 6 | 7 | 1 |
T2.plot(kind='bar');
#stacked 参数设置为False时,作出的是分段式条形图;为True时,作出的是并列式条形图
T2.plot(kind='bar', stacked=True);
# 按列分组
BSdata.groupby(['性别'])
type(BSdata.groupby(['性别'])) #使用 groupby()函数生成的是一个中间分组变量,为 GroupBy 类型
pandas.core.groupby.generic.DataFrameGroupBy
# 按分组统计
BSdata.groupby(['性别'])['身高'].mean()
性别 女 165.360000 男 171.444444 Name: 身高, dtype: float64
BSdata.groupby(['性别'])['身高'].size()
性别 女 25 男 27 Name: 身高, dtype: int64
BSdata.groupby(['性别','开设'])['身高'].mean()
性别 开设 女 不必要 165.166667 不清楚 164.555556 有必要 166.200000 男 不必要 180.200000 不清楚 173.333333 有必要 168.842105 Name: 身高, dtype: float64
# 聚集函数 agg()
BSdata.groupby(['性别'])['身高'].agg([np.mean, np.std])
mean | std | |
---|---|---|
性别 | ||
女 | 165.360000 | 5.179125 |
男 | 171.444444 | 9.103395 |
# 应用函数 apply()
BSdata.groupby(['性别'])['身高','体重'].apply(np.mean)
<ipython-input-76-30e087821a5b>:2: FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead. BSdata.groupby(['性别'])['身高','体重'].apply(np.mean)
身高 | 体重 | |
---|---|---|
性别 | ||
女 | 165.360000 | 66.240000 |
男 | 171.444444 | 70.592593 |
BSdata.groupby(['性别','开设'])['身高','体重'].apply(np.mean)
<ipython-input-77-4d7925996276>:1: FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead. BSdata.groupby(['性别','开设'])['身高','体重'].apply(np.mean)
身高 | 体重 | ||
---|---|---|---|
性别 | 开设 | ||
女 | 不必要 | 165.166667 | 67.333333 |
不清楚 | 164.555556 | 64.666667 | |
有必要 | 166.200000 | 67.000000 | |
男 | 不必要 | 180.200000 | 79.200000 |
不清楚 | 173.333333 | 72.666667 | |
有必要 | 168.842105 | 68.000000 |
#pt11=BSdata.pivot_table(values=['学号'],index=['性别'],aggfunc=len)
pt11=BSdata.pivot_table(['学号'],['性别'],aggfunc=len); pt11 #len分组长度
学号 | |
---|---|
性别 | |
女 | 25 |
男 | 27 |
pt11.plot(kind='bar');
#pt12=BSdata.pivot_table(values=['学号'],index=['性别','开设'],aggfunc=len)
pt12=BSdata.pivot_table(['学号'],['性别','开设'],aggfunc=len);pt12
学号 | ||
---|---|---|
性别 | 开设 | |
女 | 不必要 | 6 |
不清楚 | 9 | |
有必要 | 10 | |
男 | 不必要 | 5 |
不清楚 | 3 | |
有必要 | 19 |
pt12.plot(kind='bar');
#pt13=BSdata.pivot_table(values=['学号'],index=['开设'],columns=['性别'],aggfunc=len);
pt13=BSdata.pivot_table(['学号'], ['开设'], ['性别'], aggfunc=len); pt13
学号 | ||
---|---|---|
性别 | 女 | 男 |
开设 | ||
不必要 | 6 | 5 |
不清楚 | 9 | 3 |
有必要 | 10 | 19 |
pt13.plot(kind='bar');
pt13.plot(kind='bar',stacked=True);
pt21=BSdata.pivot_table(index=['性别'], values=["身高"], aggfunc=np.mean);pt21
身高 | |
---|---|
性别 | |
女 | 165.360000 |
男 | 171.444444 |
pt21.plot(kind='bar');
pt22=BSdata.pivot_table(index=['性别'], values=["身高"], aggfunc=[np.mean,np.std]);
pt22
mean | std | |
---|---|---|
身高 | 身高 | |
性别 | ||
女 | 165.360000 | 5.179125 |
男 | 171.444444 | 9.103395 |
pt22.iloc[:,0].plot(kind='bar',yerr=pt22.iloc[:,1]); #标准差条图
pt23=BSdata.pivot_table(index=["性别"], values=["身高","体重"]);pt23 # 默认计算均值
体重 | 身高 | |
---|---|---|
性别 | ||
女 | 66.240000 | 165.360000 |
男 | 70.592593 | 171.444444 |
pt23.plot(kind='bar');
pt23.plot(kind='bar',subplots=True,layout=(1,2));
BSdata.pivot_table('学号', ['性别','开设'], '课程', aggfunc=len,
margins=True, margins_name='合计')
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 | 合计 | |
---|---|---|---|---|---|---|---|
性别 | 开设 | ||||||
女 | 不必要 | 1.0 | 1.0 | NaN | 1.0 | 3.0 | 6 |
不清楚 | 2.0 | 1.0 | 3.0 | 2.0 | 1.0 | 9 | |
有必要 | NaN | 5.0 | 3.0 | 2.0 | NaN | 10 | |
男 | 不必要 | 2.0 | 1.0 | 1.0 | NaN | 1.0 | 5 |
不清楚 | 1.0 | 2.0 | NaN | NaN | NaN | 3 | |
有必要 | 5.0 | 5.0 | 3.0 | 5.0 | 1.0 | 19 | |
合计 | 11.0 | 15.0 | 10.0 | 10.0 | 6.0 | 52 |
pt31=BSdata.pivot_table('学号',['性别','开设'],'课程',aggfunc=len)
pt31
课程 | 概率统计 | 统计方法 | 编程技术 | 都学习过 | 都未学过 | |
---|---|---|---|---|---|---|
性别 | 开设 | |||||
女 | 不必要 | 1.0 | 1.0 | NaN | 1.0 | 3.0 |
不清楚 | 2.0 | 1.0 | 3.0 | 2.0 | 1.0 | |
有必要 | NaN | 5.0 | 3.0 | 2.0 | NaN | |
男 | 不必要 | 2.0 | 1.0 | 1.0 | NaN | 1.0 |
不清楚 | 1.0 | 2.0 | NaN | NaN | NaN | |
有必要 | 5.0 | 5.0 | 3.0 | 5.0 | 1.0 |
pt31.plot(kind='bar',stacked=False);
pt32=BSdata.pivot_table(['身高','体重'],['性别',"开设"],aggfunc=[len,np.mean,np.std]);pt32
len | mean | std | |||||
---|---|---|---|---|---|---|---|
体重 | 身高 | 体重 | 身高 | 体重 | 身高 | ||
性别 | 开设 | ||||||
女 | 不必要 | 6 | 6 | 67.333333 | 165.166667 | 3.326660 | 2.786874 |
不清楚 | 9 | 9 | 64.666667 | 164.555556 | 6.000000 | 6.502136 | |
有必要 | 10 | 10 | 67.000000 | 166.200000 | 5.333333 | 5.308274 | |
男 | 不必要 | 5 | 5 | 79.200000 | 180.200000 | 4.438468 | 4.147288 |
不清楚 | 3 | 3 | 72.666667 | 173.333333 | 5.033223 | 5.686241 | |
有必要 | 19 | 19 | 68.000000 | 168.842105 | 9.165151 | 9.124224 |
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]); #基于性别和开设的体重标准差条图