R语言中文社区

涵盖R官方、Rstudio、中国R语言会议等前沿分享。立即关注,掌握R语言全球最新资讯与成果!...

个人生活的量化分析(二):Apple健康数据分析

点击蓝字关注这个神奇的公众号~

作者简介

林筱越:华东政法大学 社会学专业 R语言爱好者 


往期回顾:

使用ggplot2绘制心形

定量论文:探究「健康水平、婚姻状况」对幸福感的影响

个人生活的量化分析(一):时间管理


全文目录:

1. 前言

2. 数据准备

3. 数据导入

4. 数据预处理

5. 可视化部分

6. 结语



1. 前言

因为我是一个平时经常锻炼的人,因此基本上每次下载一个有关健康的app(例如Keep、悦跑圈等),我都会允许将数据导入iPhone的自带的健康app。

可能大家平时只对于健康app使用的比较少,但是它除了能提供有关健康数据的视图部分外,其实它还提供了「数据导出」的功能,这毫无疑问也为了解自己的锻炼状况提供了分析的可能。

本次使用的数据是通过iPhone导出后的健康数据,用以看看自己之前的一些锻炼状况。


2. 数据准备

进入健康app后点击右上角的用户图标:

之后进入之后点击最下面的「Export Data」,然后iPhone会将所有健康数据以一个名为「export.zip」的压缩包形式打包,接着通过iCloud或者微信传输到电脑:

得到压缩包后解压可以得到是「xml文件」,仍然不是我们需要的csv表格或xls格式,所以这时就需要进入健康数据转化的网站(http://ericwolter.com/projects/health-export.html),然后直接将解压后的xml文件拖入当中转化后便可以得到所有健康数据了:

由于篇幅有限,在导入数据之前我已经用Excel对所有csv格式的数据做了「分列」的预先处理,并删除一些无用的列,保留了基本的数据;但这并不代表数据就已经可以完全拿来使用了,因此还需要进一步进行清洗。

本次仅选取「体重记录」、「饮水量」、「卡路里消耗」、「每日步数记录」四部分数据来进行分析。


3. 数据导入

此次为大家展示一下通过与数据库交互,来导入数据将4个csv的数据文件导入进R;在此之前已经将4个文件导入MySQL:

library(RMySQL) #读取MySQL
library(tidyverse) #数据处理、可视化
# 1. 数据导入部分
## 调用MySQL
conn <- dbConnect(MySQL(), dbname='rdata',
                  username='root',
                  password='934804',
                  host='127.0.0.1',
                  port=3306)

## 读取表格
weight <- dbReadTable(conn, 'weight')
water <- dbReadTable(conn, 'water')
steps <- dbReadTable(conn, 'step_count')
calories <- dbReadTable(conn, 'calories')


•  其中conn部分最为重要:

–   dbname:为数据库中的数据库名称

–   username:一般个人的MySQL都为「root」

–   password:是自己设定的密码(也可能为空)

–   host:一般填「127.0.0.1」

–   port:端口好一般为「3306」

•  建立好与MySQL连接的端口后,就可以使用RMySQL包中的dbReadTable函数来对数据库的表进行读取,第一个参数为端口,第二个参数为表格名称

•  不熟悉MySQL的朋友可以使用read_csv来读取,读取tidyverse包后就可以使用


4. 数据预处理

4.1 保留变量

由于这四部分数据存在着数据内容上的一致性,为了统一操作,这里其存入一个list中:

# 存入list
all_data <- list(weight, water, steps, calories)

然后这时,我们用for循环来对这四个数据进行批量操作,即保留仅需要的列:

# 通过for循环保留列
keep_cols <- c('sourceName', 'creationDate', 'value')
for (i in c(1:4)) {
  all_data[[i]] <- all_data[[i]][,keep_cols]
}

•  这里系统会提示说选择了没有定义列的警告信息,这里是因为有些数据没有sourceName这一列,但实际上并不影响列的提取,可以忽略

4.2 数据重组

由于没有使用read_csv函数导入,所以这里导入的所有数据都是字符串类型;但通过观察数据可以发现,所有数据基本都是包含时间对象和一个记录值。但时间对象我们仅需要提取「日期」即可,因此这里就需要所有数据时间对象进行日期提取。

在此之前我们先简单定义一个字符串列表分隔的函数:

# 定义提取日期函数
date_split_func <- function(name) {
  date_split <- strsplit(name$creationDate, ' ')
  date_get <- sapply(date_split, '[[', 1)
  return(as.Date(date_get))
}

•  这里需要注意的就是sapply的用法:

–   第一个参数指定的是已经被strsplit函数分割的字符串列表

–   第二个参数是索引列表中的各部分(如果大家对此有疑问的话,可以查阅《R语言实战/第5章:高级数据管理》中学生成绩排名这一案例,当中就使用到了这一函数,很实用。算是一个骚操作:p)

–   第三个参数是提取时间对象的第1列(也就是日期)

接下来就是将四个数据进行筛选和重组:

# 数据筛选与重组
weight <- all_data[[1]]
weight_date <- date_split_func(weight)
weight <- weight %>%
  select(value) %>%
  cbind(weight_date)

calories <- all_data[[4]]
calories_date <- date_split_func(calories)
calories <- calories %>%
  select(value, sourceName) %>%
  cbind(calories_date)

•  这里为了方便大家阅读,就删去当中water和steps数据的重组过程,只需要将weight数据过程中的名称和索引进行替换即可。这三个数据的重组过程完全一致

•  然后calories数据与其他三个数据不同的是,多提取了sourceName一列


5. 可视化部分

5.1 体重记录

上个寒假放假的一段期间里,我每天都会早上测量自己的体重,打算看看在开学之前自己能胖多少斤:

weight %>%
  ggplot(aes(x=weight_date, y=as.numeric(value))) +
  geom_point() +
  geom_line() +
  # 添加平均线
  # 设置颜色和线条:红色虚线,
  # alpha:透明度减少50%
  geom_hline(yintercept = mean(as.numeric(weight$value)),
             color='red', linetype='dotdash', alpha=0.5)+
  labs(x='日期(天)', y='重量(kg)', title='体重记录') +
  scale_x_date(date_breaks = '3 day') + 
 
  # 在图中添加注释
  # bolditalic为斜粗体
  # parse=T时转化为数学公式样式
  annotate(geom='text', x=weight_date[4], y=68,
           label = 'paste(bolditalic(Mean), \' = 66.94(kg)\')', parse=T) +
 
  # plot.title用于调整标题
  theme_bw() +
  theme(text = element_text(family = 'STKaiti'),
        axis.text.x = element_text(angle = 45, vjust=1, hjust = 1),
        plot.title = element_text(hjust = 0.5))

•  当中一些细节调整我已给出注释,大家对照着看应该很容易理解;后面我也不再一一重复

•  为了使图形简介,我使用scale_x_date函数稍微对x轴的日期进行分割

•   对于annotate函数中的选项,这里给大家稍微详解一下:

–  x和y的坐标实际上是我个人指定图形中的空白区域部分,为了label注释部分能很好的展示

–   label部分我使用了paste来将字符串进行黏贴,当中要注意一下「\」单斜杆的用法:用于对符号进行转化,以便系统视为「文本」的一部分

–   parse=T时,label的内容会以数学公式的样式来呈现

在放假前,我的体重是63kg。从图形可以看出,一个假期我竟然一直在胖!

5.2 饮水量记录

为了贯彻每天8杯水的饮水理念(1杯水大概500ml?),我使用了一款名为「Water Reminder」的app来进行记录,就假定水杯为500ml,所以每次就喝一半就为250ml,因此就对应记录:

# 查看平均饮水量
water %>%
  group_by(water_date) %>%
  summarize(total_water = sum(as.numeric(value))) %>%
  summarize(mean_drink = mean(total_water))

# 绘制
water_plot <- water %>%
  group_by(water_date) %>%
  summarise(total_water = sum(as.numeric(value))) %>%
  ggplot(aes(x=water_date, y=total_water))+
  geom_line() +
  labs(x='日期(每3天)', y='饮水量(毫升)', title='饮水量') +
 
  # 这里的yintercept=2802根据平均饮水量来输入
  geom_hline(yintercept = 2802, color='red',
             linetype='dotdash', alpha=0.5)+
  annotate(geom='text', x=weight_date[1], y=1000,
           label = 'paste(bolditalic(Mean), \' = 2802(ml)\')', parse=T) +
  scale_x_date(date_breaks = '3 day') +
  theme_bw() +
  theme(text = element_text(family = 'STKaiti'),
        axis.text.x = element_text(angle = 45, vjust=1,hjust = 1),
        plot.title = element_text(hjust = 0.5))

从趋势可以看出,每天饮水量在不断下降(好吧,其实有时候会懒得记或者忘记记了);没想到的是,1月19号那天我竟然喝了5L的水!

不过平均来说我每天喝水量大概也接近3000ml了(查看了一下中位数与平均数差不多,这里就没有使用中位数),总的来说每天身体的水分还是相对维持在一个平衡的状态吧!(多喝水有益健康)

5.3 卡路里消耗记录

不同app的卡路里记录

成人每日消耗大约1000~1500千卡(百度的)。手机里的卡路里记录主要由日常行走和锻炼两部分组成,虽然可能会有部分重合,但是对于整体的影响并不大,还是能较为直观的反映出平日里的能量消耗。

这里我就首先看一看我在Keep和悦跑圈两个app上锻炼时候的记录:

  # 提出分组好的数据集
diff_app <- calories %>%
  group_by(sourceName) %>%
  summarize(total_calories = sum(as.numeric(value)))

  # 创建标签
calories_label <- paste(diff_app$total_calories,'Kcal')

  # 绘制
diff_app %>%
  ggplot(aes(x=sourceName, y=total_calories, fill=factor(sourceName))) +
  geom_bar(stat='identity', show.legend = F, width = 0.3) +
  labs(x='健康App',y='总消耗卡路里(Kcal)',title='不同app的卡路里记录') +
 
  # 将标签映射到数据上
  geom_text(aes(label=calories_label), vjust = -0.2) +
  theme_bw() +
  theme(text = element_text(family='STKaiti'),
        panel.grid.major.x = element_blank(),
        plot.title = element_text(hjust = 0.5))

•  悦跑圈功能相对简单,仅作为跑步使用,消耗了3505千卡

•  Keep既提供锻炼健身动作的功能,也提供了跑步的功能,因此自己经常性使用;到目前为止也已经消耗了大约11142千卡!

2018年的卡路里记录

数据里包含了从2017年到至今的数据(期间还原过手机几次,所以更早的记录就丢失了),但这里仅选取2018年的数据:

  # 建立上年记录的索引
  # 提取本年度的记录
last_year <-seq.Date(from = as.Date('2017-01-01'),
                     to = as.Date('2017-12-31'),
                     by = 'day')
drop_index <- calories$calories_date %in% last_year
calories <- calories[which(!drop_index),]

  # 查看中位数
median(as.numeric(calories$value))

  # 绘制部分
calories %>%
  group_by(calories_date) %>%
  summarise(total_calories = sum(as.numeric(value))) %>%
  ggplot(aes(x=calories_date, y=total_calories)) +
  geom_point() +
  geom_line(alpha = 0.5) +
  geom_hline(yintercept = 83, linetype='dotdash',
             color='red', alpha=0.5) +
  labs(x='日期(月)',y='总卡路里(Kcal)', title='卡路里消耗图') +
  scale_x_date(date_breaks = 'week') +
  annotate(geom='text', x=calories$calories_date[15], y=300,
           label = 'paste(bolditalic(Median),\' = 83(Kcal)\')', parse = T) +
  theme_bw() +
  theme(text = element_text(family = 'STKaiti'),
        axis.text.x = element_text(angle = 45, vjust = 1, hjust =1),
        plot.title = element_text(hjust = 0.5))

•  这里的83千卡其实并不准确,因为这仅是手机记录的运动时消耗的能量;还缺少日常行为所消耗的能量。

•  同时,为了避免受极端值的影响,我使用了中位数来进行衡量。

可以看到的,今年是平时活动时消耗的卡路里大约是83Kcal,主要是因为今年处于备考状态,所以在锻炼上所分配的精力就少了,这也就是为什么导致记录的数据不变偏低的原因。

5.4 每日步数记录

在大一大二喜欢跑步的时候,经常会沉迷于微信运动的排行榜,不过之后就没有再关注并且关闭了微信运动(因为点赞什么的太烦)。不过每日步数的记录,也能侧面反映出一个人每日活动的状况吧:

  # 汇总数据
group_steps <- steps%>%
  group_by(steps_date) %>%
  summarize(total_steps = sum(as.numeric(value)))
  # 查看均值
mean_steps <- mean(group_steps$total_steps)

  # 绘制部分
steps_plot <- group_steps %>%
  ggplot(aes(x=steps_date, y=total_steps)) +
  geom_line() +
  labs(x='日期(周)', y='每日总步数', title='行走步数') +
  scale_x_date(date_breaks='week') +
  geom_hline(yintercept = mean_steps, linetype='dotdash',
             color='red', alpha=0.5) +
  annotate(geom='text', x=group_steps$steps_date[120], y=18000,
           label = 'paste(bolditalic(Mean),\' = 7947.88(steps)\')',
           parse = T) +
  theme_bw() +
  theme(text = element_text(family = 'STKaiti'),
        axis.text.x = element_text(angle=45, vjust=1, hjust=1),
        plot.title = element_text(hjust = 0.5))

•  从图形可以看出,基本上2017年下半年,因为课程安排的还是比较多,所以几乎每天都保持超过8000步的行走记录

•  到了今年,行走的步数也越来越少了……因为基本上每天活动的范围仅限于寝室……


6. 结语

•  分析至此,我觉得我平日里的生活习惯还是蛮健康的,也正因如此也会渐渐养成了某些保持健康的习惯。

•  iPhone的健康app记录了多种活动的数据(如果有佩戴Apple Watch可能还会记录心率之类的数据)并提供了数据导出的功能;当然,如果拥有更多健康测量的设备,那么获得的数据也许还会更多。

•  可以看出,几张可视化的分析(除了app对比的那张图外)基本上可以看作是时间序列对象的描述性分析;至于对时间序列进行分解与建模更深层次、更复杂的统计方法方面,暂时没有涉及,不过还是有深挖的可能。如果感兴趣对自己的日常行为有兴趣的朋友可以尝试去探索一番!





 大家都在看 

2017年R语言发展报告(国内)

R语言中文社区历史文章整理(作者篇)

R语言中文社区历史文章整理(类型篇)


公众号后台回复关键字即可学习

回复 R                  R语言快速入门及数据挖掘 
回复 Kaggle案例  Kaggle十大案例精讲(连载中)
回复 文本挖掘      手把手教你做文本挖掘
回复 可视化          R语言可视化在商务场景中的应用 
回复 大数据         大数据系列免费视频教程 
回复 量化投资      张丹教你如何用R语言量化投资 
回复 用户画像      京东大数据,揭秘用户画像
回复 数据挖掘     常用数据挖掘算法原理解释与应用
回复 机器学习     人工智能系列之机器学习与实践
回复 爬虫            R语言爬虫实战案例分享

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

个人生活的量化分析(二):Apple健康数据分析

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭