如何使用 tidyr 在分组变量的每个值内填写完整的行?
How do I use tidyr to fill in completed rows within each value of a grouping variable?
假设我有关于在多个选项之间做出选择的人的数据。我每人一行,我想每人一行和选择选项。所以,如果我有 10 个人有 3 个选择,那么现在我有 10 行,我想要有 30 行。
应将所有其他变量复制到每个新行。因此,例如,如果我有一个性别变量,它在 ID 中应该是常量。 (我以这种方式设置我的数据以使用 mnlogit
进行分析。)
这似乎是两个 tidyr
函数 complete
和 fill
专门针对的情况。举个简单的例子:
library(lubridate)
library(tidyr)
dat <- data.frame(
id = 1:3,
choice = 5:7,
c = c(9, NA, 11),
d = ymd(NA, "2015-09-30", "2015-09-29")
)
dat %>%
complete(id, choice) %>%
fill(everything())
# Source: local data frame [9 x 4]
#
# id choice c d
# (int) (int) (dbl) (time)
# 1 1 5 9 <NA>
# 2 1 6 9 <NA>
# 3 1 7 9 <NA>
# 4 2 5 9 <NA>
# 5 2 6 9 2015-09-30
# 6 2 7 9 2015-09-30
# 7 3 5 9 2015-09-30
# 8 3 6 9 2015-09-30
# 9 3 7 11 2015-09-29
但这有一些问题 -- d 的值被正确地继承,但是 ID 1 中的 c 值替换了 ID 2 的(正确的)NA 值。
我可以尝试一种解决方法,比如用 999、运行 complete
和 fill
替换所有缺失值,然后用 NA 替换 999。 (我想如果我走这条路,我必须将日期变量转换为字符变量,然后再将它们转换回来。)但也许这里有人知道用 tidyr
?[=19 做这个的简洁方法=]
编辑:此处所需的输出是:
# Source: local data frame [9 x 4]
#
# id c d choice
# (int) (dbl) (time) (int)
# 1 1 9 <NA> 5
# 2 1 9 <NA> 6
# 3 1 9 <NA> 7
# 4 2 NA 2015-09-30 5
# 5 2 NA 2015-09-30 6
# 6 2 NA 2015-09-30 7
# 7 3 11 2015-09-29 5
# 8 3 11 2015-09-29 6
# 9 3 11 2015-09-29 7
您可以使用 "grouping" 的技巧来完成使用 c()
完成的事情。这使得它只能使用分组变量的预先存在的组合来完成。
library(tidyr)
dat %>% complete(c(id, c, d), choice)
id c d choice
(int) (dbl) (time) (int)
1 1 9 <NA> 5
2 1 9 <NA> 6
3 1 9 <NA> 7
4 2 NA 2015-09-30 5
5 2 NA 2015-09-30 6
6 2 NA 2015-09-30 7
7 3 11 2015-09-29 5
8 3 11 2015-09-29 6
9 3 11 2015-09-29 7
我认为你最好在准备数据时将数据分开,然后在需要进行回归之前合并。
subjectdata <- dat[,c("id", "c", "d")]
questiondata <- dat[,c("id", "choice")] %>% complete(id, choice)
然后
> merge(questiondata, subjectdata)
id choice c d
1 1 5 9 <NA>
2 1 6 9 <NA>
3 1 7 9 <NA>
4 2 5 NA 2015-09-30
5 2 6 NA 2015-09-30
6 2 7 NA 2015-09-30
7 3 5 11 2015-09-29
8 3 6 11 2015-09-29
9 3 7 11 2015-09-29
根据需要。这样,您还可以获得用户 2 的有效 d
列,而不依赖于数据框中问题的顺序。
看起来另一种方法是使用 spread
和 gather
。 spread
为每个可能的答案创建一列,而 gather
将单独的列重新整形为行。有了这些数据:
dat %>%
spread(choice, choice) %>%
gather(choice, drop_me, `5`:`7`) %>% # Drop me is a redundant column
select(-drop_me) %>%
arrange(id, choice) # reorders so that the answer matches
# id c d choice
# 1 1 9 <NA> 5
# 2 1 9 <NA> 6
# 3 1 9 <NA> 7
# 4 2 NA 2015-09-30 5
# 5 2 NA 2015-09-30 6
# 6 2 NA 2015-09-30 7
# 7 3 11 2015-09-29 5
# 8 3 11 2015-09-29 6
# 9 3 11 2015-09-29 7
我还没有进行任何测试来比较它们的效率。
作为对@jeremycg 回答的更新。从 tidyr 0.5.1
(甚至版本 0.4.0
)开始,c()
不再有效。使用 nesting()
代替:
dat %>%
complete(nesting(id, c, d), choice)
注意 我试图编辑@jeremycg 的答案,因为答案在写的时候是正确的(因此并不是真的需要一个新的答案)但不幸的是编辑被拒绝。
假设我有关于在多个选项之间做出选择的人的数据。我每人一行,我想每人一行和选择选项。所以,如果我有 10 个人有 3 个选择,那么现在我有 10 行,我想要有 30 行。
应将所有其他变量复制到每个新行。因此,例如,如果我有一个性别变量,它在 ID 中应该是常量。 (我以这种方式设置我的数据以使用 mnlogit
进行分析。)
这似乎是两个 tidyr
函数 complete
和 fill
专门针对的情况。举个简单的例子:
library(lubridate)
library(tidyr)
dat <- data.frame(
id = 1:3,
choice = 5:7,
c = c(9, NA, 11),
d = ymd(NA, "2015-09-30", "2015-09-29")
)
dat %>%
complete(id, choice) %>%
fill(everything())
# Source: local data frame [9 x 4]
#
# id choice c d
# (int) (int) (dbl) (time)
# 1 1 5 9 <NA>
# 2 1 6 9 <NA>
# 3 1 7 9 <NA>
# 4 2 5 9 <NA>
# 5 2 6 9 2015-09-30
# 6 2 7 9 2015-09-30
# 7 3 5 9 2015-09-30
# 8 3 6 9 2015-09-30
# 9 3 7 11 2015-09-29
但这有一些问题 -- d 的值被正确地继承,但是 ID 1 中的 c 值替换了 ID 2 的(正确的)NA 值。
我可以尝试一种解决方法,比如用 999、运行 complete
和 fill
替换所有缺失值,然后用 NA 替换 999。 (我想如果我走这条路,我必须将日期变量转换为字符变量,然后再将它们转换回来。)但也许这里有人知道用 tidyr
?[=19 做这个的简洁方法=]
编辑:此处所需的输出是:
# Source: local data frame [9 x 4]
#
# id c d choice
# (int) (dbl) (time) (int)
# 1 1 9 <NA> 5
# 2 1 9 <NA> 6
# 3 1 9 <NA> 7
# 4 2 NA 2015-09-30 5
# 5 2 NA 2015-09-30 6
# 6 2 NA 2015-09-30 7
# 7 3 11 2015-09-29 5
# 8 3 11 2015-09-29 6
# 9 3 11 2015-09-29 7
您可以使用 "grouping" 的技巧来完成使用 c()
完成的事情。这使得它只能使用分组变量的预先存在的组合来完成。
library(tidyr)
dat %>% complete(c(id, c, d), choice)
id c d choice
(int) (dbl) (time) (int)
1 1 9 <NA> 5
2 1 9 <NA> 6
3 1 9 <NA> 7
4 2 NA 2015-09-30 5
5 2 NA 2015-09-30 6
6 2 NA 2015-09-30 7
7 3 11 2015-09-29 5
8 3 11 2015-09-29 6
9 3 11 2015-09-29 7
我认为你最好在准备数据时将数据分开,然后在需要进行回归之前合并。
subjectdata <- dat[,c("id", "c", "d")]
questiondata <- dat[,c("id", "choice")] %>% complete(id, choice)
然后
> merge(questiondata, subjectdata)
id choice c d
1 1 5 9 <NA>
2 1 6 9 <NA>
3 1 7 9 <NA>
4 2 5 NA 2015-09-30
5 2 6 NA 2015-09-30
6 2 7 NA 2015-09-30
7 3 5 11 2015-09-29
8 3 6 11 2015-09-29
9 3 7 11 2015-09-29
根据需要。这样,您还可以获得用户 2 的有效 d
列,而不依赖于数据框中问题的顺序。
看起来另一种方法是使用 spread
和 gather
。 spread
为每个可能的答案创建一列,而 gather
将单独的列重新整形为行。有了这些数据:
dat %>%
spread(choice, choice) %>%
gather(choice, drop_me, `5`:`7`) %>% # Drop me is a redundant column
select(-drop_me) %>%
arrange(id, choice) # reorders so that the answer matches
# id c d choice
# 1 1 9 <NA> 5
# 2 1 9 <NA> 6
# 3 1 9 <NA> 7
# 4 2 NA 2015-09-30 5
# 5 2 NA 2015-09-30 6
# 6 2 NA 2015-09-30 7
# 7 3 11 2015-09-29 5
# 8 3 11 2015-09-29 6
# 9 3 11 2015-09-29 7
我还没有进行任何测试来比较它们的效率。
作为对@jeremycg 回答的更新。从 tidyr 0.5.1
(甚至版本 0.4.0
)开始,c()
不再有效。使用 nesting()
代替:
dat %>%
complete(nesting(id, c, d), choice)
注意 我试图编辑@jeremycg 的答案,因为答案在写的时候是正确的(因此并不是真的需要一个新的答案)但不幸的是编辑被拒绝。