R语言数据处理——Tidyr包
参考教程https://4va.github.io/biodatasci/r-tidy.html#review
练习数据下载:https://4va.github.io/biodatasci/data.html
感觉老外写的教程很详细,搭配国内的教程可以更好地学习。本文主要是针对Tidyr包的学习。这个包还是很有用的。
1 先来明白什么是Tidy data数据
Tidy data数据集有两个关键属性。
每一列都是一个变量。
每一行都是一个观察值。
2 看看untidy的数据长啥样
library(readr)
hr <- read_csv("heartrate2dose.csv")
hr

这个数据的基本内容:
五个不同的name病人(Jon, Ann, Bill, Kate和Joe)服用三种不同的drug药物(A, B, C),两种dose剂量(10和20),测量他们的heart rate心率的数据。
本次数据中有4个变量,name,drug,dose,heart rate。
drug和dose这两个变量绑在了一起。heart rate数据分散在整个列表。对于后续的操作是非常不利的。
例如:我们想通过某些条件过滤数据,使用 filter函数过滤 drug=="a" or dose==20 or heartrate>=80,我们无法操作,因为这些变量的数据不是在某一列中。
3 tidyr package
这个包中主要有两个函数 separate() and gather().
可以使用?separate() ,?gather()查看帮助文档。
gather()函数的作用是:操作多个列,并这些列gather成键-值对的形式。这使得“宽”数据变得更长。
separate()函数的作用是:将一个列分成多个列
首次使用需要安装和下载包:
install.packages("tidyr")
library(tidyr)
4 实战,处理数据
drug/dose 绑在一块,heart rate数据分散在列表。我们分两次操作
4.1,先将drug和dose对应的heart rate对应的多个列数据,用gather命令生成key-value的形式。
gather(hr,key=drugdose,value=hr,a_10, a_20, b_10, b_20, c_10, c_20)
hr %>% gather(key=drugdose, value=hr, a_10, a_20, b_10, b_20, c_10, c_20)
#%>%是R语言中的管道符,相当于Linux中的管道符。将hr数据框传递给后面的函数
第一个参数是要进行变形的数据。
接下来的两个参数是要创建的键和值列的名称,后面的所有相关参数都是我们想要聚集在一起的列
也可以简化操作
hr %>% gather(key=drugdose, value=hr, a_10:c_20)
用一个冒号表示a-10到c-20的所有列
也可以用一个-直接排除我们不想gather的列
hr %>% gather(key=drugdose, value=hr, -name)
这步操作后,实际效果如下:

可以清楚看到,生成新的两列。原来分散的hr变成了长数据。
但是,还有一个问题未解决,drug和dose这两个变量纠缠一起。下面,我们要用separate()函数给分开。
4.2 separate() 函数
hr %>%
gather(key=drugdose, value=hr, -name) %>%
separate(drugdose, into=c("drug", "dose"), sep="_")
drugdose是要分割列,into内包含要分割成的两列。sep是分割符号,也就是按照“_”对drugdose的数据进行分割。sep的参数也可以是一个数字,指示要分割的位置。
效果如下

可以清楚看到每列是一个变量,每行是一个观测值。这就是我们要的tidy数据。
4.3 最后使用管道符连接起来,并且赋给一个新的变量hrtidy
hrtidy <- hr %>%
gather(key=drugdose, value=hr, -name) %>%
separate(drugdose, into=c("drug", "dose"), sep="_")
4.4 可以使用其他函数进行分析了
# filter
hrtidy %>% filter(drug=="a")
hrtidy %>% filter(dose==20)
hrtidy %>% filter(hr>=80)
# analyze
hrtidy %>%
filter(name!="joe") %>%
group_by(drug, dose) %>%
summarize(meanhr=mean(hr)