数据分析3 - 数据分析方法

基本统计

基本统计分析,也叫描述性统计分析,用来概括事物整体状况以及事物间联系(即事物的基本特征),以发现其内在规律的统计分析方法

基本统计是同一字段下值的统计,也既是 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 分析过程:

  1. 计算 RFM 各项分值
    • R_S,距离当前时间越近,得分越高,1-5
    • F_S,交易频率越高,得分越高,1-5
    • M_S,交易金额越高,得分越高,1-5
  2. 汇总 RFM 分值
    RFM = 100 * R_S + 10 * F_S + 1 * M_S
  3. 根据 RFM 分值对客户分类

RFM 分析前提:

  1. 最近有交易行为的客户,再次发生交易的可能性要高于最近没有交易行为的客户;
  2. 交易频率较高的客户比交易频率较低的客户,更有可能再次发生交易行为;
  3. 过去所有交易总金额较多的客户,比交易总金额较少的客户,更有消费积极性
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()


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容