如何避免使用pivot_wider()函数时删除列名的因子水平?

13

我希望pivot_wider创建一个列,如果作为names_from参数时因为因子的级别存在但从未在数据中出现而创建NAs。例如,第一行给了我一个两列的表格,但我真的希望下面是三列的表格。

tibble(Person=c("Sarah", "Jackson", "Jackson"), Rank=c(1,1,2), 
       FavoriteAnimal=factor(c("Dog", "Dog", "Cat")))%>%
    group_by(Person)%>%arrange(Rank)%>%slice(1)%>%
    pivot_wider(names_from = FavoriteAnimal, values_from=Rank)
我如何在数据集中没有出现的水平上获取我的NA列?

5
尝试使用参数names_expand = TRUE,该参数在tidyr 1.2.0中已经提供。 - Patrick
4个回答

9

另外一种方法是,您可以先添加缺失的级别,然后进行转换:

tibble(Person = c("Sarah", "Jackson", "Jackson"), 
       Rank = c(1, 1, 2), 
       FavoriteAnimal = factor(c("Dog", "Dog", "Cat"))) %>%
 group_by(Person) %>%
 arrange(Rank) %>% 
 slice(1) %>%
 complete(FavoriteAnimal = FavoriteAnimal) %>%
 pivot_wider(names_from = FavoriteAnimal, values_from = Rank)

  Person    Cat   Dog
  <chr>   <dbl> <dbl>
1 Jackson    NA     1
2 Sarah      NA     1

2
不知道完整函数,这太棒了!只是一个注意事项——这仅在我们仍在使用分组 tibble 时才能按预期工作! - jntrcs

7

您可以在 pivot_wider 中使用 names_expand = TRUE 来包含所有因子水平:

tib %>%
  pivot_wider(names_from = FavoriteAnimal, values_from = Rank, 
              names_expand = TRUE)

  Person    Cat   Dog
  <chr>   <dbl> <dbl>
1 Jackson    NA     1
2 Sarah      NA     1

数据

tib <- tibble(Person=c("Sarah", "Jackson", "Jackson"), Rank=c(1,1,2), 
       FavoriteAnimal=factor(c("Dog", "Dog", "Cat")))%>%
  group_by(Person)%>%arrange(Rank)%>%slice(1)

5
你可以使用tidyr::spread来实现 - spread(key = FavoriteAnimal, value = Rank, drop = FALSE) 即可得到所需结果。
不幸的是在从spread转换为pivot_wider时,drop参数似乎已经被删除了。

1
看起来这个问题有一个Github问题 - IceCreamToucan
FYI - tidy::spread 在 tidyr 1.1.4 版本中已被 pivot_wider 取代。 - ESELIA

0
似乎您的slice(1)操作正在删除Jackson的Cat排名。如果您从操作中将其删除,并添加pivot_wider参数values_fill = NA,则会得到一个3列tbl。我的答案与您的目标唯一不同之处在于,我的答案保留了Jackson的Cat排名值。
tibble(Person=c("Sarah", "Jackson", "Jackson"), Rank=c(1,1,2), 
       FavoriteAnimal=factor(c("Dog", "Dog", "Cat")))%>%
    group_by(Person)%>%arrange(Rank)%>%
    pivot_wider(names_from = FavoriteAnimal, values_from=Rank, values_fill = NA)

根据dplyr :: slice的帮助文档,似乎您正在尝试为每个人仅选择排名最高的动物,因此此解决方案无法实现。但是,根据您的需求,可能有其他方法,例如使用dplyr :: select或dplyr :: filter,也许结合dplyr :: across来实现此目的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接