基本统计
基本统计分析,也叫描述性统计分析,用来概括事物整体状况以及事物间联系(即事物的基本特征),以发现其内在规律的统计分析方法
基本统计是同一字段下值的统计,也既是 Series 的统计
常用的统计指标 | 对应的统计函数 |
---|---|
最大值 | series.max() |
最小值 | series.min() |
计数 | series.size |
求和 | series.sum() |
平均值 | series.mean() |
方差 | series.var() |
标准差 | series.std() |
描述性统计分析函数:series.describe()
,获取一个字典,key 有:count(行数) mean(平均值) std(标准差) max(最大值) min(最小值) 25%(1/4 分位值) 50%(中位值) 75%(3/4 分位值)
series.cumsum()
累计求和,返回一个 Series,当前值是上一个元素的值+原 series 所在位置的值
series.argmax()
最大值所在位置
series.argmin()
最小值所在位置
series.quantile()
求百分位对应的值
import pandas
data = pandas.read_csv(
'data.csv'
)
# 获取一个字典,key 有:count(行数) mean(平均值) std(标准差) max(最大值) min(最小值) 25%(1/4 分位值) 50%(中位值) 75%(3/4 分位值)
data.score.describe()
data.score.size
data.score.max()
data.score.min()
data.score.sum()
data.score.mean()
data.score.var()
data.score.std()
#累计求和
data.score.cumsum()
#最大值和最小值所在位置
data.score.argmin()
data.score.argmax()
# 求百分位数
# interpolation="nearest" —— 如果找不到精确的百分位数,取离它最近的
data.score.quantile(
0.3,
interpolation="nearest"
)
分组分析
分组分析指根据分组字段,将分析对象划分成不同的部分,以进行对比分析各组之间的差异性 的一种分析方法
分组的目的是进行各组之间的对比分析
分组类型主要有两大类:定性分组(按业务类别的属性划分,如性别,年龄,地区) 与 定量分组(即数值分组)
常用的统计指标:
- 计数
- 求和
- 平均值
分组统计函数:
groupby(by=[分组列1, 分组列2, ...])
[统计列1, 统计列2, ...]
.agg({统计列别名1:统计函数1, 统计列别名2:统计函数2, ...})
参数 | 注释 |
---|---|
by | 用于分组的列(按什么进行分组) |
中括号 | 用于统计的列 |
agg | 统计别名显示统计值的名称,统计函数用于统计数据 |
groupby(by=[分组列1, 分组列2, ...]) 得到一个 DataFrameGroupBy 实例
groupby(by=[分组列1, 分组列2, ...])[统计列1, 统计列2, ...] 如果是只选中一个字段则是 SeriesGroupBy 实例,选中多个是 DataFrameGroupBy 实例
groupby(by=[分组列1, 分组列2, ...])[统计列1, 统计列2, ...].agg({统计列别名1:统计函数1, 统计列别名2:统计函数2, ...}) 得到一个 DataFrame 实例,以 by 所指向的字段名组成 (分组列1, 分组列2, ...) 为 index ,以 统计列别名为字段名
常见的统计函数:
- size
- sum
- mean
import numpy
import pandas
data = pandas.read_csv(
'data.csv'
)
aggResult = data.groupby(
by=['class']
)['score'].agg({
'总分': numpy.sum,
'人数': numpy.size,
'平均值': numpy.mean
})
分布分析
分布分析指根据分析目的,将数据(定量数据)进行等距或者不等距的分组,进行研究各组分布规律的一种分析方法
分布分析是分组分析的一种,但针对需要进行分组的字段的值过于分散,需要用到数组分组将值位于区段内的数据分成一组,再用分组后的字段用与分组分析
import numpy
import pandas
data = pandas.read_csv(
'data.csv'
)
# 按分组分析,然而年龄的个数太多
aggResult = data.groupby(
by=['年龄']
)['年龄'].agg({
'人数': numpy.size
})
#查看年龄的直方图
data.年龄.hist()
# 进行数组分组
bins = [
min(data.年龄)-1, 20, 30, 40, max(data.年龄)+1
]
labels = [
'20岁以及以下', '21岁到30岁', '31岁到40岁', '41岁以上'
]
data['年龄分层'] = pandas.cut(
data.年龄,
bins,
labels=labels
)
# 再根据分组后的字段进行分组分析
aggResult = data.groupby(
by=['年龄分层']
)['年龄'].agg({
'人数': numpy.size
})
# 取百分比
pAggResult = round(
aggResult/aggResult.sum(),
2
)*100
pAggResult['人数'].map('{:,.2f}%'.format)
交叉分析
交叉分析通常用于分析两个或两个以上,分组变量之间的关系,以交叉表形式进行变量间关系的对比分析
- 定量、定量分组交叉
- 定量、定性分组交叉
- 定性、定性分组交叉
交叉统计函数:pivot_table(values,index,columns,aggfunc,fill_value)
参数 | 注释 |
---|---|
values | 数据透视表中的值 |
index | 数据透视表中的行 |
columns | 数据透视表中的列 |
aggfunc | 统计函数 |
fill_value | nan 值的统一替换 |
import numpy
import pandas
data = pandas.read_csv(
'data.csv'
)
# 数组分组
bins = [
min(data.年龄)-1, 20, 30, 40, max(data.年龄)+1
]
labels = [
'20岁以及以下', '21岁到30岁', '31岁到40岁', '41岁以上'
]
data['年龄分层'] = pandas.cut(
data.年龄,
bins,
labels=labels
)
ptResult = data.pivot_table(
values=['年龄'],
index=['年龄分层'],
columns=['性别'],
aggfunc=[numpy.size]
)
结构分析
结构分析是在分组以及交叉的基础上,计算各组成部分所占的比重,进而分析总体的内部特征的一种分析方法
axis = 0 按列运算(默认),axis = 1 按行运算
数据框的外运算(两个数据框之间的运算)函数:
dataFrame.add(series)
dataFrame.sub(series)
dataFrame.multiply(series)
dataFrame.div(series)
数据框的内运算(数据框自身的运算)函数:
dataFrame.sum()
dataFrame.mean()
dataFrame.var()
dataFrame.std()
import numpy
import pandas
data = pandas.read_csv(
'data.csv'
)
bins = [
min(data.年龄)-1, 20, 30, 40, max(data.年龄)+1
]
labels = [
'20岁以及以下', '21岁到30岁', '31岁到40岁', '41岁以上'
]
data['年龄分层'] = pandas.cut(
data.年龄,
bins,
labels=labels
)
ptResult = data.pivot_table(
values=['年龄'],
index=['年龄分层'],
columns=['性别'],
aggfunc=[numpy.size]
)
# 结构分析
ptResult.sum()
ptResult.sum(axis=0)
ptResult.sum(axis=1)
ptResult.div(ptResult.sum(axis=1), axis=0)
ptResult.div(ptResult.sum(axis=0), axis=1)
相关分析
相关分析是研究两个或以上随机变量之间相互依存关系的方向和密切程度的方法
相关关系可分为:
- 线性相关
- 非线性相关
线性相关关系主要采用皮尔逊( Pearson )相关系数 r 来度量连续变量之间线性相关强度,r > 0 表示线性正相关,反之则反:
r 的取值范围 | 相关程度 |
---|---|
0<=|r|<0.3 | 低度相关 |
0.3<=|r|<0.8 | 中度相关 |
0.8<=|r|<=1 | 高度相关 |
相关分析函数:
dataFrame.corr()
series.corr(otherSeries)
如果由 DataFrame 调用 corr 方法,那么将会计算每个列两两之间的相似度,返回一个 DataFrame,大小为 列数 * 列数
如果由 Series 调用 corr 方法,那么只是计算该序列与传入的序列之间的相似度,返回一个数值
import pandas
data = pandas.read_csv(
'data.csv'
)
# 两个列之间的相关度的计算
data['人口'].corr(data['文盲率'])
# 数据框字段与字段之间的相关度的计算方法
data[[
'超市购物率', '网上购物率', '文盲率', '人口'
]].corr()
RFM 分析
RFM 分析是根据客户活跃度和交易金额贡献,进行客户价值细分的一种方法:
指标 | 解释 | 意义 |
---|---|---|
R(Recency)近度 | 最近一次交易的时间间隔 | R越大表示客户越久未发生交易 |
F(Frequency)频度 | 最近一段时间的交易次数 | F越大交易越频繁 |
M(Monetary)额度 | 最近一段时间的交易金额 | M越大客户价值越高 |
RFM 分析过程:
- 计算 RFM 各项分值
- R_S,距离当前时间越近,得分越高,1-5
- F_S,交易频率越高,得分越高,1-5
- M_S,交易金额越高,得分越高,1-5
- 汇总 RFM 分值
RFM = 100 * R_S + 10 * F_S + 1 * M_S
- 根据 RFM 分值对客户分类
RFM 分析前提:
- 最近有交易行为的客户,再次发生交易的可能性要高于最近没有交易行为的客户;
- 交易频率较高的客户比交易频率较低的客户,更有可能再次发生交易行为;
- 过去所有交易总金额较多的客户,比交易总金额较少的客户,更有消费积极性
import numpy
import pandas
data = pandas.read_csv(
'data.csv'
)
# 转换为 date 数据类型
data['DealDateTime'] = pandas.to_datetime(
data.DealDateTime,
format='%Y/%m/%d'
)
# 求交易日期与今天的差值
data['DateDiff'] = pandas.to_datetime(
'today'
) - data['DealDateTime']
# 保存为天数
data['DateDiff'] = data['DateDiff'].dt.days
# 以用户为单位,求最近的交易日期距离的天数
R_Agg = data.groupby(
by=['CustomerID']
)['DateDiff'].agg({
'RecencyAgg': numpy.min
})
# 以用户为单位,求交易的次数
F_Agg = data.groupby(
by=['CustomerID']
)['OrderID'].agg({
'FrequencyAgg': numpy.size
})
# 以用户为单位,求交易的金额总数
M_Agg = data.groupby(
by=['CustomerID']
)['Sales'].agg({
'MonetaryAgg': numpy.sum
})
# 汇成一张表
aggData = R_Agg.join(F_Agg).join(M_Agg)
# 进行数组分组,求出对应的分数
# 对最近的交易日期距离的天数求百分位
bins = aggData.RecencyAgg.quantile(
q=[0, 0.2, 0.4, 0.6, 0.8, 1],
interpolation='nearest'
)
bins[0] = 0
labels = [5, 4, 3, 2, 1]
R_S = pandas.cut(
aggData.RecencyAgg,
bins, labels=labels
)
bins = aggData.FrequencyAgg.quantile(
q=[0, 0.2, 0.4, 0.6, 0.8, 1],
interpolation='nearest'
)
bins[0] = 0;
labels = [1, 2, 3, 4, 5];
F_S = pandas.cut(
aggData.FrequencyAgg,
bins, labels=labels
)
bins = aggData.MonetaryAgg.quantile(
q=[0, 0.2, 0.4, 0.6, 0.8, 1],
interpolation='nearest'
)
bins[0] = 0
labels = [1, 2, 3, 4, 5]
M_S = pandas.cut(
aggData.MonetaryAgg,
bins, labels=labels
)
aggData['R_S']=R_S
aggData['F_S']=F_S
aggData['M_S']=M_S
# 再按公式求 RFM
aggData['RFM'] = 100*R_S.astype(int) + 10*F_S.astype(int) + 1*M_S.astype(int)
# 再按分数分等级
bins = aggData.RFM.quantile(
q=[
0, 0.125, 0.25, 0.375, 0.5,
0.625, 0.75, 0.875, 1
],
interpolation='nearest'
)
bins[0] = 0
labels = [1, 2, 3, 4, 5, 6, 7, 8]
aggData['level'] = pandas.cut(
aggData.RFM,
bins, labels=labels
)
# 按用户ID重新排序
aggData = aggData.reset_index()
# 按RFM LEAVEL 重新排序
aggData.sort_values(
['level', 'RFM'],
ascending=[True, True]
)
# 统计各个level 下的用户数
aggData.groupby(
by=['level']
)['CustomerID'].agg({
'size':numpy.size
})
矩阵分析
矩阵分析指根据事物(如产品、服务等)的两个重要属性(指标)作为分析的依据,根据关联分析,找出解决问题的一种分析方法
import pandas
import matplotlib
import matplotlib.pyplot as plt
mainColor = (42/256, 87/256, 141/256, 1);
#设置字体
font = {
'family': 'SimHei',
'size': 20
}
matplotlib.rc('font', **font);
data = pandas.read_csv(
'data.csv'
)
# 设置要画的图形格式,大小、像素
fig = plt.figure(
figsize=(30, 20),
dpi=80
)
# add_subplot 获取子图,111 表示分为一行一列操作第一个子图
sp = fig.add_subplot(111)
# 设置 x y 轴的值的范围
# x轴DGP
sp.set_xlim([
0,
data.GDP.max()*1.1
])
# y轴人口
sp.set_ylim([
0,
data.population.max()*1.1
])
#关闭坐标轴
#sp.axis('off')
# 关闭坐标轴的刻度值
sp.get_xaxis().set_ticks([])
sp.get_yaxis().set_ticks([])
#画点
sp.scatter(
data.GDP,
data.population,
alpha=0.5,
s=200,
marker="o",
edgecolors=mainColor,
linewidths=5
)
# 画均值线
sp.axvline(
x=data.GDP.mean(),
linewidth=1, color=mainColor
)
sp.axhline(
y=data.population.mean(),
linewidth=1, color=mainColor
)
sp.axvline(
x=0,
linewidth=3, color=mainColor
)
sp.axhline(
y=0,
linewidth=3, color=mainColor
)
# 设置 x轴、y轴的 label
sp.set_xlabel('GDP')
sp.set_ylabel('人口')
#画标签
data.apply(
lambda row: plt.text(
row.GDP,
row.population,
row.province,
fontsize=15
),
axis=1
)
plt.show()