通过使用dplyr添加包含序列号的变量来扩展(爆炸?)data.frame

时间:2019-03-20 13:23:38

标签: r dplyr

我有一个简单的数据框,可以说:

dd <- data.frame(id = letters[1:4], v1 = c(0.3,0.1,0.7,1.3))
dd
  id  v1
1  a 0.3
2  b 0.1
3  c 0.7
4  d 1.3

对于此数据帧的每一行,我想通过添加一个给出数字序列的新变量来“分解”它。我成功完成了此操作,但这是我的代码不理想且几乎没有消耗:

dd %>% 
  mutate("0"=0,"5"=5,"10"=10) %>% 
  reshape2::melt(id.vars=c("id", "v1")) %>% 
  select(-variable) 
   id  v1 value
1   a 0.3     0
2   b 0.1     0
3   c 0.7     0
4   d 1.3     0
5   a 0.3     5
6   b 0.1     5
7   c 0.7     5
8   d 1.3     5
9   a 0.3    10
10  b 0.1    10
11  c 0.7    10
12  d 1.3    10

因此,在此示例中,我为每一行添加了一个名为value的列,该列在c(0,5,10)内具有所有三个值

此代码并不理想,因为我想要的实际序列几乎是1:70,并且我不想手动在我的mutate中编写所有70个新变量。当然有更好的方法,您能帮我吗?

我不必呆在dplyr中,但我希望可以通过它传递代码。

谢谢

6 个答案:

答案 0 :(得分:3)

library(tidyr)
dd %>% crossing(value = c(0, 5, 10))
   id  v1 value
1   a 0.3     0
2   a 0.3     5
3   a 0.3    10
4   b 0.1     0
5   b 0.1     5
6   b 0.1    10
7   c 0.7     0
8   c 0.7     5
9   c 0.7    10
10  d 1.3     0
11  d 1.3     5
12  d 1.3    10

答案 1 :(得分:2)

一种选择是在数据框中添加值,并在基数R中执行merge

merge(dd, data.frame(value = c(0, 5, 10)))

#   id  v1 value
#1   a 0.3     0
#2   b 0.1     0
#3   c 0.7     0
#4   d 1.3     0
#5   a 0.3     5
#6   b 0.1     5
#7   c 0.7     5
#8   d 1.3     5
#9   a 0.3    10
#10  b 0.1    10
#11  c 0.7    10
#12  d 1.3    10

答案 2 :(得分:1)

我们还可以使用expand包中的tidyr

library(tidyverse)

dd <- data.frame(id = letters[1:4], v1 = c(0.3,0.1,0.7,1.3))

dd %>% 
  expand(nesting(id, v1), value = seq(0, 10, by = 5)) %>%
  arrange(value, id)
# # A tibble: 12 x 3
#    id       v1 value
#    <fct> <dbl> <dbl>
#  1 a       0.3     0
#  2 b       0.1     0
#  3 c       0.7     0
#  4 d       1.3     0
#  5 a       0.3     5
#  6 b       0.1     5
#  7 c       0.7     5
#  8 d       1.3     5
#  9 a       0.3    10
# 10 b       0.1    10
# 11 c       0.7    10
# 12 d       1.3    10

答案 3 :(得分:1)

使用lapply(一种非常强大的工具)的解决方案:

dd <- data.frame(id = letters[1:4], v1 = c(0.3,0.1,0.7,1.3))
newdf<- lapply(c(0,5,10), function(value) {
   cbind(dd, data.frame(value=rep(value,NROW(dd))))
})
newdf <- do.call('rbind',newdf)

#    id  v1 value
#1   a 0.3     0
#2   b 0.1     0
#3   c 0.7     0
#4   d 1.3     0
#5   a 0.3     5
#6   b 0.1     5
#7   c 0.7     5
#8   d 1.3     5
#9   a 0.3    10
#10  b 0.1    10
#11  c 0.7    10
#12  d 1.3    10

答案 4 :(得分:1)

使用splitstackshape套餐参加聚会,

library(splitstackshape)

transform(expandRows(dd, count = 3, count.is.col = FALSE), value = c(0, 5, 10))

#    id  v1 value
#1    a 0.3     0
#1.1  a 0.3     5
#1.2  a 0.3    10
#2    b 0.1     0
#2.1  b 0.1     5
#2.2  b 0.1    10
#3    c 0.7     0
#3.1  c 0.7     5
#3.2  c 0.7    10
#4    d 1.3     0
#4.1  d 1.3     5
#4.2  d 1.3    10

答案 5 :(得分:1)

使用data.table

setDT(dd)[, .(value = c(0, 5, 10)), by = .(id, v1)]

输出:

    id  v1 value
 1:  a 0.3     0
 2:  a 0.3     5
 3:  a 0.3    10
 4:  b 0.1     0
 5:  b 0.1     5
 6:  b 0.1    10
 7:  c 0.7     0
 8:  c 0.7     5
 9:  c 0.7    10
10:  d 1.3     0
11:  d 1.3     5
12:  d 1.3    10

如果您加载了magrittr(或者如果您已经加载了dplyrtidyverse),则可以继续使用管道setDT(dd)[, .(value = c(0, 5, 10)), by = .(id, v1)] %>% ...