r - 用 dplyr 整理多列
问题描述
我知道 data.table 能够一次整理多个列,这与 dplyr 不同,dplyr 依赖于难以可视化的多个gather
步骤spread
。
这是 tidyverse 的一个棘手问题:
library(tidyverse)
df <- data_frame(month_1 = c("Jan", "Feb", "Mar", "Jun"),
score_1 = c(4, 5, 6, 4),
month_2 = c("Jan", "Mar", NA, NA),
score_2 = c(3, 2, NA, NA),
month_3 = c("Feb", "Mar", "Jun", NA),
score_3 = c(8, 7, 4, NA))
# A tibble: 4 x 6
month_1 score_1 month_2 score_2 month_3 score_3
<chr> <dbl> <chr> <dbl> <chr> <dbl>
1 Jan 4 Jan 3 Feb 8
2 Feb 5 Mar 2 Mar 7
3 Mar 6 NA NA Jun 4
4 Jun 4 NA NA NA NA
我想要的结果是:
id month score
1 Jan 4
1 Feb 5
1 Mar 6
1 Jun 4
2 Jan 3
2 Mar 2
3 Feb 8
3 Mar 7
3 Jun 4
data.table 用户可以通过融合模式来解决这个问题,例如:
melt(setDT(df), measure = patterns("^month", "^score"))
但由于没有等效的 dplyr 函数,我知道需要几个spread
. 看起来我下面的解决方案应该可以工作,但第二个spread
出错了:
df %>%
gather(key, value) %>%
mutate(id = parse_number(key),
key = str_replace(key, "_[0-9]", "")) %>%
spread(key, value )
在将此标记为重复之前,请尝试一下。类似问题在现有列中具有唯一 ID。此示例在标头中有 id。
解决方案
您可以分别处理month
和score
列,然后将它们加入purrr::map_dfc
:
map_dfc(c("month", "score"),
~ df %>%
select_at(vars(matches(.x))) %>%
gather(key, !!.x) %>%
separate(key, c("col", "id"), sep="_")) %>%
filter(complete.cases(.)) %>%
select(id, month, score)
# A tibble: 9 x 3
id month score
<chr> <chr> <chr>
1 1 Jan 4
2 1 Feb 5
3 1 Mar 6
4 1 Jun 4
5 2 Jan 3
6 2 Mar 2
7 3 Feb 8
8 3 Mar 7
9 3 Jun 4
解释:
map_dfc
遍历字符串值“month”和“score”,将当前值称为.x
.dfc
后缀对迭代输出执行acbind
。select_at
仅选择以开头的列.x
gather
从宽到长摆动,并用字符串值 命名values
列。.x
separate
分成key
两列,包含列类型(对应于.x
值)和id
数字。- 一旦映射和列绑定完成,我们就会
filter
删除缺失值和select
目标列。
推荐阅读
- react-native - 顶部选项卡导航 wix 反应本机导航应用程序正在崩溃
- c - C上的尾递归双因子 - 整数除以零
- react-native - 使用未定义状态响应本机 PanResponder 函数调用
- laravel - Chrome 无法打开 localhost:3000 BrowserSync
- flutter - 如何在卡片内添加 PopupMenuButton
- c - 如何从循环单链表中删除一个节点
- node.js - 使用打字稿节点js express返回具有接口函数类型的对象
- python - Python - 此函数中的变量如何通过字典进行?
- python - 如何使用单个 shell 实例在 Python 中运行多个命令?(避免shell启动时间)
- database - 试图从数据库中获取记录并传递给控制器