添加新的列名称以在spread()中使用

时间:2018-11-27 21:11:32

标签: r dplyr tidyr

大图:我正在尝试建立一个导出,该导出的每个值的行和列都有一条路由。

这段代码:我正在尝试为每条路线选择前三个传输(使用slice(1:3),因为我不需要多于三个值。top_n()允许平局)。然后,我尝试spread()创建6列:每个列的名称和pct。

如果我现在要散布数据,则名称将变为列,但我需要将名称保留在行中(请参见所需的输出)。我想将列名称创建为要用于spread()的键列。我的方法是创建一个错误。我在想另一种策略时遇到了麻烦。

数据框:

# A tibble: 7 x 3
route_shortname transfer_to   pct
<chr>           <chr>       <dbl>
1 A               D           0.5  
2 A               E           0.5  
3 B               F           0.667
4 B               G           0.333
5 C               D           0.111
6 C               E           0.111
7 C               G           0.111

所需的输出:

# A tibble: 3 x 7
route_shortname transfer1 transfer1_pct transfer2 transfer2_pct transfer3 transfer3_pct
<chr>           <chr>             <dbl> <chr>             <dbl> <chr>             <dbl>
1 A               D                 0.5   E                 0.5   NA               NA    
2 B               F                 0.667 G                 0.333 NA               NA    
3 C               D                 0.111 E                 0.111 G                 0.111

代表:

library(tidyverse)

sample_data <- tibble::tribble(
  ~route_shortname, ~transfer_to,              ~pct,
  "A",                "D",               0.5,
  "A",                "E",               0.5,
  "B",                "F", 0.666666666666667,
  "B",                "G", 0.333333333333333,
  "C",                "D", 0.111111111111111,
  "C",                "E", 0.111111111111111,
  "C",                "G", 0.111111111111111
)

transfer_to_table <- sample_data %>%
  group_by(route_shortname) %>%
  mutate(key = c("transfer1", "transfer2", "transfer3"))

#> Error in mutate_impl(.data, dots): Column `key` must be length 2 (the group size) or one, not 3

2 个答案:

答案 0 :(得分:0)

df = read.table(text = "
route_shortname transfer_to   pct
1 A               D           0.5  
2 A               E           0.5  
3 B               F           0.667
4 B               G           0.333
5 C               D           0.111
6 C               E           0.111
7 C               G           0.111
", header=T)

library(tidyverse)

df %>%
  group_by(route_shortname) %>%
  mutate(id = paste0("transfer", row_number())) %>%
  ungroup() %>%
  unite(v, transfer_to, pct) %>%
  spread(id, v) %>%
  separate(transfer1, c("transfer1","transfer1_pct"), sep = "_", convert = T) %>%
  separate(transfer2, c("transfer2","transfer2_pct"), sep = "_", convert = T) %>%
  separate(transfer3, c("transfer3","transfer3_pct"), sep = "_", convert = T)

#   route_shortname transfer1 transfer1_pct transfer2 transfer2_pct transfer3 transfer3_pct
#   <fct>           <chr>             <dbl> <chr>             <dbl> <chr>             <dbl>
# 1 A               D                 0.5   E                 0.5   NA               NA    
# 2 B               F                 0.667 G                 0.333 NA               NA    
# 3 C               D                 0.111 E                 0.111 G                 0.111

答案 1 :(得分:0)

尽管您已用tidyverse包标记了这个问题,但这是一个使用dcast中的data.table的选项,让您在一行(允许很长)的行中进行重塑。

library(data.table)
setDT(sample_data)
dcast(sample_data, route_shortname ~ rowid(route_shortname), value.var = c('transfer_to', 'pct'))
#   route_shortname transfer_to_1 transfer_to_2 transfer_to_3     pct_1     pct_2     pct_3
#1:               A             D             E          <NA> 0.5000000 0.5000000        NA
#2:               B             F             G          <NA> 0.6666667 0.3333333        NA
#3:               C             D             E             G 0.1111111 0.1111111 0.1111111

您还可以使用reshape中的base R

sample_data <- as.data.frame(sample_data) # does not work with tibbles for some reason
sample_data$idx <- with(sample_data,
                        ave(route_shortname, route_shortname, FUN = seq_along))
reshape(sample_data, idvar = "route_shortname", timevar = "idx", direction = "wide", sep = "_")
#  route_shortname transfer_to_1     pct_1 transfer_to_2     pct_2 transfer_to_3     pct_3
#1               A             D 0.5000000             E 0.5000000          <NA>        NA
#3               B             F 0.6666667             G 0.3333333          <NA>        NA
#5               C             D 0.1111111             E 0.1111111             G 0.1111111

在两种情况下,您都需要重命名列,但我应该不会太难。