如何收集和填写范围内的值

时间:2019-05-10 04:21:42

标签: r dplyr tidyr

我正在尝试从宽数据转换为长数据,但是遇到了特定问题。每个人在旅馆里都有一排房间,但我只知道他们的第一个和最后一个房间。我想填写第一个房间和最后一个房间之间的房间。

data = read.table(text="
   name  first_room  last_room
   A   2  5
   B   4   7", header=TRUE)

我正在尝试获得每个人的所有房间,包括中间的房间。

我已经尝试过在提德尔中使用Gather,但这只会给我第一个和最后一个房间。

data %>% gather(type, room, -1) %>% arrange(name)

当前输出:

     name    type room
 1    A first_room    2
 2    A  last_room    5
 3    B first_room    4
 4    B  last_room    7

想要的输出:

   Name       type room
 1    A first_room    2
 2    A  last_room    3
 3    A  last_room    4
 4    A  last_room    5
 5    B first_room    4
 6    B first_room    5
 7    B first_room    6
 8    B first_room    7

2 个答案:

答案 0 :(得分:3)

一个选项是按“名称”分组之后,从complete到“房间”的first元素中依次得到一个last序列,然后是fill

library(tidyverse)
data %>% 
   gather(type, room, -1) %>%
   arrange(name) %>% 
   group_by(name) %>%
   complete(room = seq(room[1], room[2]))  %>% 
   fill(type, .direction = "up")
# A tibble: 8 x 3
# Groups:   name [2]
#  name   room type      
#  <fct> <int> <chr>     
#1 A         2 first_room
#2 A         3 last_room 
#3 A         4 last_room 
#4 A         5 last_room 
#5 B         4 first_room
#6 B         5 last_room 
#7 B         6 last_room 
#8 B         7 last_room 

答案 1 :(得分:1)

这是一种更手动的方法。我可能将akrun的解决方案与complete一起使用,但这是另一种选择。这在某些方面更普遍...如果您想要类似但不太完整的序列,可以用它做一些更奇怪的事情。

data %>% mutate(room = Map(seq, from = data$first_room, to = data$last_room)) %>%
  tidyr::unnest() %>%
  select(name, room) %>%
  group_by(name) %>%
  mutate(type = if_else(row_number() == 1, "first room", "last_room"))
# # A tibble: 8 x 3
# # Groups:   name [2]
#   name   room type      
#   <fct> <int> <chr>     
# 1 A         2 first room
# 2 A         3 last_room 
# 3 A         4 last_room 
# 4 A         5 last_room 
# 5 B         4 first room
# 6 B         5 last_room 
# 7 B         6 last_room 
# 8 B         7 last_room