ggplot2-数据整理2

1. separate和unite

spread和gather函数可以帮助解决数据中的变量放错了位置的问题,而separate和unite则是为了解决以下问题:多个变量挤在了同一列中,或是一个变量分散到了不同的列中

举个例子,以下数据集记录了某种药物治疗的响应数据。它包含三个变量(时间、治疗状态和响应值),但是时间和治疗状态的数据被记在一起了,变成了一个变量:

trt <- dplyr::data_frame(var = paste0(rep(c("beg", "end"), each = 3), "_", rep(c("a", "b", "c"))), val = c(1, 4, 2, 10, 5, 11))
trt

separate()函数可以轻而易举地将这一混杂的列拆分成多个变量,它包含以下四个主要参数

  1. data 需要调整地数据框
  2. col 需要进行拆分的列的列名
  3. into 拆分后新生成变量的列名,格式为字符型变量
  4. sep 对如何拆分原变量的描述,其可以是正则表达式,如_表示通过下划线拆分,或[^a-z]表示通过任意非字母字符拆分,或一个指定位置的整数

在这个例子中,用_字符进行拆分

separate(trt, var, c("time", "treatment"), "_")

(如果变量被一种更复杂的形式混合在一起,可以尝试以下extract()函数,另外如果需要单独建立一列经由某种运算生成的变量,mutate()函数是一种方法)

unite()函数是separate()的逆运算——它可以将多列合并为一列。尽管不常用,但知道其实separate()的逆函数还是很有必要的

2. 案例学习

对于大部分真实数据,需要运用的整理命令不止一个。虽然有很多路径可以走,但是只要每一步都让数据集更整洁一些,最终总会得到一个令人满意的整洁数据集。这意味着,通常会以相同的顺序使用这些函数:gather()、separate()和spread()(虽然并不一定每个都会用到)

1. 血压

数据整理的第一步:确定数据集里的变量。看下面这个模拟医疗数据的数据集,其中有7个变量:姓名、年龄、开始日期、星期、收缩压和舒张压。它是以什么形式存储的?

# 从Barry Rowlingson的例子修改而来
# http://barryrowlingson.github.io/hadleyverse/
bpd <- readr::read_table(
"name	age	start	week1	week2	week3
Anne	35	2014-03-27	100/80	100/75	120/90
Ben	41	2014-03-09	110/65	100/65	135/70
Carl	33	2014-04-02	125/80	<NA>	<NA>
", na = "<NA>"
)

首先,化宽为长:

bpd_1 <- gather(bpd, week, bp, week1:week3)
bpd_1

数据看起来更整洁了,但是有两个变量(收缩压与舒张压)被一起记录在bp变量下。尽管经常这么记录血压,但是把它们分开菜更易于分析。separate就可以做到

bpd_2 <- separate(bpd_1, bp, c("sys", "dia"), "/")
bpd_2

这个数据集现在已经很整洁了,但可以再进一步让它变得更好用。下面的代码中运用了extract()函数,将week列中的数字单独取出来作为该列的值。还利用了arrange()函数对行进行了排列以使每个人的记录都聚在一起

bpd_3 <- extract(bpd_2, week, "week", "(\\d)", convert = TRUE)
bpd_4 <- dplyr::arrange(bpd_3, name, week)
bpd_4

可能会注意到这个数据集存在一定的重复:如果知道了姓名,自然就知道了年龄与开始时间。这反映了整洁的第三个条件:每个数据框应该有且仅有一个数据集。而这里事实上包含了两个数据集:不随时间改变的个人信息,和他们每周的血压测量值。

2. 考试成绩

# 修改自 https://stackoverflow.com/questions/29775461
set.seed(127)
scores <- dplyr::data_frame(
	person = rep(c("Greg", "Sally", "Sue"), each = 2),
	time = rep(c("pre", "post"), 3),
	test1 = round(rnorm(6, mean = 80, sd = 4), 0),
	test2 = round(jitter(test1, 15), 0)
)
scores

变量包括人、考试、干预前成绩、干预后成绩。像之前那样,先将宽数据(test1和test2)转换为长数据形式(test和score)

scores_1 <- gather(scores, test, score, test1:test2)
scores_1

接下来,需要做一件相反的事:pre(前)和post(后)应当是两个变量而非值,所以我们要展开time和score变量

scores_2 <- spread(scorres_1, time, score)
scores_2

我们将数据集整理好的一个重要证据是,它现在很容易计算出想要的统计量,即干预前后的成绩差值

scores_3 <- mutate(scores_2, diff = post - pre)
score_3

接下来作图就很容易了

ggplot(scores_3, aes(person, diff, color = test)) +
	geom_hline(size = 2, color = "white", yintercept = 0) +
	geom_point() +
	geom_path(aes(group = person), color = "grey50",
	arrow = arrow(length = unit(0.25, "cm")))

了解更多

数据整理是一个很大的话题,本章只触及其表面,关于其更深层次的讨论,推荐以下参考文献

  • tidyr包的文档
  • Tidy data
  • data wrangling cheatsheet
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值