数据分析实战---墨西哥人肥胖程度

517 阅读12分钟

本次数据来源于kaggle

数据提取: 链接:pan.baidu.com/s/1SBE_apWr… 提取码:z43v

关于数据分析报告的撰写可以参考:数据分析之必备技能---数据分析报告 - 掘金 (juejin.cn)

业务背景和数据介绍

本项目为墨西哥人肥胖程度数据可视化分析,通过数据分析挖掘影响肥胖的主要因素。

列名类型说明
Gender字符型性别
Age浮点型年龄
Height浮点型身高(m)
Weight浮点型体重(kg)
family_history_with_overweight字符型家庭成员是否患有或患有超重
FAVC字符型是否经常吃高热量的食物
FCVC浮点型平时吃饭吃蔬菜的频率
NCP浮点型一天中进餐次数
CAEC字符型两餐之间进食情况
SMOKE字符型是否抽烟
CH2O浮点型每天喝水量(L)
SCC字符型是否检测每天卡路里
FAF浮点型运动的频率(天)
TUE浮点型每日使用技术设备的时间
CALC字符型喝酒的频率
MTRANS字符型通常使用的交通方式
NObeyesdad字符型肥胖程度等级

了解清楚各字段的含义后,我们就可以进行数据分析了

数据读取

import pandas as pd
data = pd.read_csv('D:\study\data\ObesityDataSet_raw_and_data_sinthetic.csv')
print(data.head())

查看数据基本情况

import pandas as pd
data = pd.read_csv('D:\study\data\ObesityDataSet_raw_and_data_sinthetic.csv')
print(data.info())

从info()函数结果中可以看出,数据集中共包含2111条数据,没有缺失数据;根据数据的类型可以得知,本数据集包含8个数值型字段与9个非数值型字段。

查看数据的统计情况

import pandas as pd
data = pd.read_csv('D:\study\data\ObesityDataSet_raw_and_data_sinthetic.csv')
print(data.describe(include='all'))

在打印数据统计信息时,我们希望可以观察到所有字段的统计情况,而不是收尾字段的统计信息(即对所有的行和列都进行一个展示),我们只需要加入几行代码就可以解决这个问题

import pandas as pd
#设置value的显示长度为200,默认为50
pd.set_option('max_colwidth',200)
#显示所有列,把行显示设置成最大
pd.set_option('display.max_columns', None)
#显示所有行,把列显示设置成最大
pd.set_option('display.max_rows', None)
data = pd.read_csv('D:\study\data\ObesityDataSet_raw_and_data_sinthetic.csv')
print(data.describe(include='all'))

在常规的数值型数据中,我们可以直接通过describe()函数得出相对应的平均值(mean),标准差(std),最小值(min),分位数(25%,75%,50%),最大值(max);但是如果是字符型数据,我们可以得出该字段的最高频率(freq),属性数(unique)

注意!!!

describe()函数中不传入参数include='all'的话,默认只对数值型特征做运算

通过这些指标,可以对此数据集做一个初步的判断。比如:字段Gender中,Male 的人数达到1068人,而总人数为2111人,因此可以初步判断男女的数量较为平均;字段family_history_with_overweight 中,回答为yes的人数达到1726人,由于总人数为2111人,因此可以初步判断大部分的人都有家族肥胖历史。

肥胖影响因素可视化分析

探究非数值型字段的分布情况

通过分别探究非数值型和数值型数据,可以更加直观地看出来数据的具体分布情况,以及各个字段的数据情况。接下来,由于非数值型数据中,字段family_history_with_overweight , FAVC,SMOKE和Scc的数据为yes或者no,所以可以通过一张堆叠条形图展示。

家族患病史,高热量食物摄入,抽烟及卡路里检测情况的统计分析

非数值型数据主要表示为'yes'和'no',通过对两个字符的统计,我们就可以统计出数据中家庭成员患有超重的情况、经常吃高热量食物情况、抽烟情况及每天检测卡路里的情况。

family_yes = data[data['family_history_with_overweight']=='yes']['family_history_with_overweight'].count()
family_no = data['family_history_with_overweight'].count() - family_yes

high_cal_yes = data[data['FAVC'] == 'yes']['FAVC'].count()
high_cal_no = data["FAVC"].count() - high_cal_yes

smo_cal_yes = data[data['SMOKE'] == 'yes']['SMOKE'].count()
smo_cal_no = data["SMOKE"].count() - smo_cal_yes

test_cal_yes = data[data['SCC']=='yes']['SCC'].count()
test_cal_no = data['SCC'].count() - test_cal_yes

通过count()函数可以看出,在2111人中,1726个人家庭成员患有肥胖或超重,1866个人常吃高热量食物,44个人抽烟,96个人每天检测卡路里

我们通过条形图的形式对以上数据进行一个展示

import matplotlib.pyplot as plt
answer = ['yes', 'no']
labels = ['家族肥胖史', '高热量食物', '是否抽烟', '每天检测卡路里']
yes_lable = [family_yes, high_cal_yes, smo_cal_yes, test_cal_yes]
no_lable = [family_no, high_cal_no,smo_cal_no, test_cal_no]
width = 0.355
fig, ax = plt.subplots()
ax.bar(labels, yes_lable, width, label='yes', color='royalblue')
ax.bar(labels, no_lable, width, label='no', color='blue')
ax.set_ylabel('人数')
ax.set_title('非数值型字段发布情况')
ax.legend()
plt.show()

强调: matplotlib默认不支持中文显示,我们需要在引入包后进行设置

import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #该语句解决图像中的乱码问题

从图中可以明显看出,大部分的墨西哥人都存在家族肥胖史的问题,大多数人都有摄入高热量食物的习惯;所调查的这部分人群几乎全部不吸烟并且没有每日检测卡路里的习惯。

喝酒频率的统计分析

首先我们进行字段的分布情况进行一个了解

data['CALC'].value_counts()

通过value_counts()函数我们可以看出在2111人中,有1401的人偶尔喝酒,639人不喝酒,70人频繁喝酒,1人经常喝酒

我们通过pyecharts绘制饼图对上述数据进行可视化

from pyecharts.charts import Pie
c = (
    Pie()
    .add(
    "",
            [list(z) for z in zip(['Sometimes', 'no', 'Frequently', 'Always'], data['CALC'].value_counts().tolist())],
            radius=["30%", "45%"],
        )
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
        .set_global_opts(tooltip_opts =opts.TooltipOpts(formatter=" {a} </br> {b} {d}%",axis_pointer_type = "cross",),legend_opts =opts.LegendOpts(type_='scroll',orient='vertical',pos_left="5%",pos_top= 'middle'),title_opts=opts.TitleOpts(title="喝酒频率分布图",pos_left="center"))

)
c.render(path="Bing1.html")

pyecharts会生成一个Bing1.html文件

从图中可以得知,大部分人有时会喝些酒,另外一大部分是不喝酒的,很少一部分经常喝酒

饮酒&进食情况分析

我们知道,肥胖和我们的饮酒情况、进食情况有很大关系,我们通过多变量观察法,分别分析饮酒的频率及两餐之间的进食情况

list1 = [data[data['CALC']=='Sometimes']['CALC'].count(), data[data['CAEC']=='Sometimes']['CAEC'].count()]
list2 = [data[data['CALC']=='no']['CALC'].count(), data[data['CAEC']=='no']['CAEC'].count()]
list3 = [data[data['CALC']=='Frequently']['CALC'].count(), data[data['CAEC']=='Frequently']['CAEC'].count()]
list4 = [data[data['CALC']=='Always']['CALC'].count(), data[data['CAEC']=='Always']['CAEC'].count()]

通过直方图进行两者关系的观察

from pyecharts.charts import Bar

d = (
Bar()
    .add_xaxis(['喝酒频率','两餐之间进食情况'])
    .add_yaxis('偶尔', [1401, 1765], stack="stack1")
    .add_yaxis("从不", [639, 51], stack="stack2")
    .add_yaxis("总是", [70, 242], stack="stack3")
    .add_yaxis("经常", [1, 53], stack="stack4")
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
    .set_colors(["#d65f5f","#8c613c","#dc7ec0","#797979"])
    .set_global_opts(tooltip_opts =opts.TooltipOpts(axis_pointer_type = "cross",),legend_opts =opts.LegendOpts(type_='scroll',orient='vertical',pos_right="5%",pos_top= 'middle'),title_opts=opts.TitleOpts(title="饮酒频率 & 两餐进食情况",pos_left="center"))
    )
d.render(path='zhi1.html')

从图中可以看出,偶尔喝酒的人数占比较大,几乎是从不喝酒人数的两倍;大部分人都有偶尔两餐之间进食的习惯,较小一部分会有经常两餐之间进食的习惯。

利用直方图探究数值型字段的分布情况

import matplotlib.pyplot as plt
import seaborn as sns
col1 = data.columns[[1,2,3,6,7,10,12,13]].tolist()
fig,ax = plt.subplots(2,4,figsize = (8,6))
column_name = ['年龄','身高(m)','体重(kg)','平时吃饭吃蔬菜的频率','一天中进餐次数','每天喝水量(L)','运动的频率(天)','每日使用技术设备的时间']

j=0
for i in range(0,len(col1)):
    plt.subplot(int('24'+str(i+1)))
    x = data[col1[i]]
    sns.distplot(x,color = 'skyblue')
    tit=column_name[j]
    j = j+1
    plt.title(tit+'直方图',size=10)

plt.tight_layout()
plt.show()

根据_上方各个连续性特征的直方图分布情况,可以判断每个字段的特点。首先,根据Age的直方图可以看出,此数据集主要研究的人的年龄分布大多在20岁到25岁之间;体重整体分布较为集中,没有明显的离群值。

关于饮食习惯,此数据中包含的人群中大多平时吃蔬菜的频率在2和3之间;其中,-天中进餐次数大多在3次,但也有相当一部分人群进餐次数较少为1次;人群的每天喝水量集中分布在2L。关于日常生活习惯方面,通过此直方图可以得出,大多数人的运动频率较为高;其中该人群使用电子产品的时间多分布在0-2小时之内。

利用热力图探究数值型字段的相关性

pandas的corr()函数可以直接得到数据的相关性

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
d = pd.DataFrame(data=data,  columns=data.columns)
corr = d.corr()
mask = np.triu(np.ones_like(corr, dtype=bool))
f, ax = plt.subplots(figsize=(8, 6))
cmap = sns.diverging_palette(200, 20, as_cmap=True)
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.6, center=0, square=True, linewidths=.8, cbar_kws={"shrink": 5})
rc = {'font.sans-serif': 'SimHei', 'axes.unicode_minus': False}
sns.set(context='notebook', style='ticks', rc=rc)
ax.set_title('数值型字段热力图')
plt.show()

由图可知,大部分特征之间存在较弱的相关性,Height 和Weight之间存在相对较强的正相关性,TUE (每日使用技术设备的时间)和Age之间存在相对较强的负相关性。因此可以初步判断此数据集所包含的年龄段在25岁左右的火,使用电子设备的时间较长。

利用散点图探究年龄和使用技术设备时间的关系

通过上面热力图初步得知年龄和使用电子设备之间存在较强的负相关性,接下来用散点图具体查看二者关系。

sns.scatterplot(data=data, x=data['Age'], y=data['TUE'],size =8,color = "#0000FF",legend = False)
plt.xlabel('Age', fontsize=8)
plt.ylabel('TUE', fontsize=8)
plt.show()

从图中可以得知,年龄在20岁左右的人群整体使用技术设备的时间较长,随着年龄的增长,每日使用技术设备的时间在减少。

利用饼图探究,肥胖程度与性别的关系

首先我们先了解一下肥胖程度的划分

data['NObeyesdad'].unique()

根据不同的肥胖程度分为七个不同的等级,我们利用饼图对肥胖程度与性别的关系进行可视化处理

# 女性中中`NObeyesdad`分布数据
female_type = ['正常', '超重I', '超重II','肥胖I', '体重不足', '肥胖II','肥胖III']
female_data = data[data['Gender']=='Female'].groupby(['NObeyesdad']).size().tolist()
# 男性中中`NObeyesdad`分布数据
male_type = ['正常', '超重I', '超重II','肥胖I', '体重不足', '肥胖II','肥胖III']
male_type.reverse()
male_data = data[data['Gender']=='Male'].groupby(['NObeyesdad']).size().tolist()
male_data.reverse()
# 数据赋值 之 内部 饼图
inner_x_data = ["女性", "男性"]
inner_y_data = data.groupby(['Gender']).size().tolist()
inner_data_pair = [list(z) for z in zip(inner_x_data, inner_y_data)]
# 数据赋值 之 外部 饼图
outer_x_data = female_type + male_type
outer_y_data = female_data + male_data
outer_data_pair = [list(z) for z in zip(outer_x_data, outer_y_data)]
# 参数配置
(
    Pie(init_opts=opts.InitOpts())
    .add(
        series_name="性别:",
        data_pair=inner_data_pair,
        radius=[0, "30%"],        # 饼图半径大小范围
        center=["45%","55%"],     # 饼图圆心相对位置
        label_opts=opts.LabelOpts(position="inner",formatter="{b} {d}%"),
        rosetype = ['radius']     # 展示成南丁格尔图
    )
    .add(
        series_name="肥胖程度:",
        data_pair=outer_data_pair,
        radius=["31%","50%"],
        center=["45%","55%"],
        label_opts=opts.LabelOpts(position="outer"),
        rosetype = ['radius']     # 展示成南丁格尔图
       )
     # 设置颜色,为了更加直观,颜色数量等同 legend数量
    .set_colors(['#44a0d6',"#fc7716","#74c476","#9e9ac8","#4c72b0","#ee854a","#6acc64","#d65f5f","#8c613c","#dc7ec0","#797979","#d5bb67","#82c6e2","#faceb6","#fae9b6","#e3fab6","#b6faf6","#d6b6fa"])
    .set_global_opts(tooltip_opts =opts.TooltipOpts(formatter=" {a} </br> {b} {d}%",axis_pointer_type = "cross",),legend_opts =opts.LegendOpts(type_='scroll',orient='vertical',pos_left="5%",pos_top= 'middle'),title_opts=opts.TitleOpts(title="性别 & 肥胖程度",pos_left="center"))
    .render("bing2.html")
    )

图中可以得知,此数据集的男女比例分布较为平均,其中男性中肥胖程度l的人较多,占比达到13.97%,其次是超重I和肥胖I;女性中体重不足的占比较多,达到15.3%,其次是正常和超重II。从中可以看出,男性比女性肥胖人群更多,女性中体重不足的人偏多。

我们也可以通过groupby()函数对上述结果进行查找

data.groupby(['Gender', 'NObeyesdad']).size().reset_index().sort_values(0, ascending=False)

利用柱状图探究肥胖程度与饮酒频率的关系

plt.figure(figsize=(8,6))
ax = sns.countplot(x='NObeyesdad',order = ['Insufficient_Weight', 'Normal_Weight', 'Overweight_Level_I', 'Overweight_Level_II','Obesity_Type_I', 'Obesity_Type_II', 'Obesity_Type_III'],hue='CALC',data=data, palette="Set2")
ax.set_xticklabels(ax.get_xticklabels(),rotation=30,size = 10)

从此柱状图中得知,喝酒频率和患肥胖症状并不存在明显的因果关系

利用箱线图探究肥胖程度与年龄的关系

plt.figure(figsize=(10,6))
ax = sns.boxplot(x=data['NObeyesdad'],order = ['Insufficient_Weight', 'Normal_Weight', 'Overweight_Level_I', 'Overweight_Level_II','Obesity_Type_I', 'Obesity_Type_II','Obesity_Type_III'],y=data['Age'],palette="Set3")
ax.set_xticklabels(ax.get_xticklabels(),rotation=30,size = 10)
plt.title('不同肥胖程度人群年龄分布')
plt.show()

通过图中箱线图,Normal_ Weight 和Insufficient_ Weight 的箱线图分布较为集中,因此可以得出正常体重和体重不足的人多集中在二十岁左右;然而肥胖人群的分布较为分散,整体分布在20到30岁之间,可以得出随着年龄趋近于30岁,人更容易患肥胖症状。其中,Obesity_ Type_ I的人群跨度最大,从20岁到50均有分布,因此可以看出患肥胖l型和年龄没有明显的相关性,各个年龄段均可能患此肥胖症。

总结

该数据是关于墨西哥人肥胖程度的相关数据,首先通过查询数值型和非数值型数据的基本信息和分布情况,对数据有一个大致的了解,然后通过热力图初步判断之后需要探究哪些字段之间的相关性;由于从热力图中得出年龄与使用技术设备之间存在一定的负相关性,因此绘制散点图展示此关系。接着,此次案例探究了肥胖程度与性别、饮酒频率和家庭肥胖史之间的关系,并分别用饼图,柱状图以及箱线图展示,

通过上述探索性分析得到的图形,可以得出主要三个点:

  • 首先,关于此数据集的一个基本情况是男女分布较为均衡都在20~25岁左右;
  • 其次,男性比女性更容易患肥胖症状,肥胖症状非常容易受到家族肥胖症状的影响;
  • 最后,年龄越小使用技术设备的时间越长。