pivot_wider 解散排列

Posted

技术标签:

【中文标题】pivot_wider 解散排列【英文标题】:pivot_wider dissolves arrange 【发布时间】:2022-01-05 18:17:01 【问题描述】:

我尝试按字母顺序对每一行进行排序(为了解决这个问题Reshaping a dataframe in R by sorting just some fields in a row alphabetically:

这是数据框:

df <- structure(list(ALT_1 = c("GAT", "TGC", "AGC", "T"), ALT_2 = c("CAG", 
"TGA", "CGC", NA), ALT_3 = c("G", NA, "TGA", NA), ALT_4 = c("AGT", 
NA, NA, NA)), class = "data.frame", row.names = c(NA, -4L))

  ALT_1 ALT_2 ALT_3 ALT_4
1   GAT   CAG     G   AGT
2   TGC   TGA  <NA>  <NA>
3   AGC   CGC   TGA  <NA>
4     T  <NA>  <NA>  <NA>

预期输出:

  ALT_1 ALT_2 ALT_3 ALT_4
1   AGT   CAG     G   GAT
2   TGA   TGC    NA    NA
3   AGC   CGC   TGA    NA
4     T    NA    NA    NA

为了实现这一点,我使用以下代码:

library(dplyr)
library(tidyr)
df %>% 
  mutate(id = row_number()) %>% 
  pivot_longer(
    -id
  ) %>% 
  group_by(id) %>% 
  arrange(value, .by_group = TRUE) %>% 
  pivot_wider(
    names_from = name,
    values_from = value
  )

然后得到这个:

     id ALT_4 ALT_2 ALT_3 ALT_1
  <int> <chr> <chr> <chr> <chr>
1     1 AGT   CAG   G     GAT  
2     2 NA    TGA   NA    TGC  
3     3 NA    CGC   TGA   AGC  
4     4 NA    NA    NA    T

我发现问题出在哪里: 如果我在pivot_longer 之后停止并在分组后使用arrange,那么一切都很好:

但是当我使用pivot_wider 转回时,订单就会消失。喜欢这里:

这样做的原因是names_from 参数保持它来自的原始顺序 -> 这里name

我想知道 有没有办法保留pivot_wider之前由arrange安排的订单?

【问题讨论】:

你能解释一下排序的逻辑吗?为什么第一行使用 tgc vs. tga 而不是第二行?我是否正确地假设您想要对每一行进行排序? 逻辑是按水平和字母顺序对每一行进行排序。非排序是在pivot_wider 之后的失败示例。查看预期输出。是的,对每一行进行排序。谢谢。 我很困惑,因为在您的预期输出中,第二行没有排序。 嗯,好的。谢谢德申。只要我在台式电脑上就会改变。 我冒昧地编辑了它。 【参考方案1】:

我们可以使用pmap 循环遍历行,使用sortna.last = TRUE

library(purrr)
pmap_dfr(df, ~ setNames(sort(c(...), na.last =TRUE), names(df)))

-输出

# A tibble: 4 × 4
  ALT_1 ALT_2 ALT_3 ALT_4
  <chr> <chr> <chr> <chr>
1 AGT   CAG   G     GAT  
2 TGA   TGC   <NA>  <NA> 
3 AGC   CGC   TGA   <NA> 
4 T     <NA>  <NA>  <NA> 

如果我们想使用pivot_longer/pivot_wider,而不是arrange,请在mutate 中使用sort,因为arrange 不会破坏“名称”列的顺序。

library(dplyr)
library(tidyr)
df %>% 
  mutate(id = row_number()) %>% 
  pivot_longer(
    -id
  ) %>% 
  group_by(id) %>% 
  mutate(value = sort(value, na.last = TRUE)) %>% 
  ungroup %>%
  pivot_wider(
    names_from = name,
    values_from = value
  ) %>%
  select(-id)

-输出

# A tibble: 4 × 4
  ALT_1 ALT_2 ALT_3 ALT_4
  <chr> <chr> <chr> <chr>
1 AGT   CAG   G     GAT  
2 TGA   TGC   <NA>  <NA> 
3 AGC   CGC   TGA   <NA> 
4 T     <NA>  <NA>  <NA> 

【讨论】:

在您的解释中,您的意思是sort 不会中断...而不是arrange @TarJae 我的意思是arrange 将整行排列为一个单元,而sort 分别对单个列进行排序【参考方案2】:

您也可以使用rowwise 执行类似于pmap 方法的操作

df <- structure(list(ALT_1 = c("GAT", "TGC", "AGC", "T"), ALT_2 = c("CAG", 
"TGA", "CGC", NA), ALT_3 = c("G", NA, "TGA", NA), ALT_4 = c("AGT", 
NA, NA, NA)), class = "data.frame", row.names = c(NA, -4L))

library(dplyr, warn.conflicts = FALSE)

df %>%
  rowwise() %>%
  mutate(c_across(everything()) %>%
    sort(na.last = TRUE) %>%
    as.data.frame.list() %>%
    setNames(names(df)))
#> # A tibble: 4 × 4
#> # Rowwise: 
#>   ALT_1 ALT_2 ALT_3 ALT_4
#>   <chr> <chr> <chr> <chr>
#> 1 AGT   CAG   G     GAT  
#> 2 TGA   TGC   <NA>  <NA> 
#> 3 AGC   CGC   TGA   <NA> 
#> 4 T     <NA>  <NA>  <NA>

由reprex package (v2.0.1) 于 2021 年 11 月 28 日创建

【讨论】:

【参考方案3】:

只是为了好玩,还有一个:

df %>%
  rowwise() %>%
  mutate(new = list(sort(c_across(everything())))) %>%
  ungroup() %>%
  select(new) %>%
  unnest_wider(new, names_repair = ~names(df))

【讨论】:

以上是关于pivot_wider 解散排列的主要内容,如果未能解决你的问题,请参考以下文章

R语言tidyr包pivot_longer函数pivot_wider函数数据表变换实战(长表到宽表宽表到长表)

作业2.有重复全排列和无重复全排列的区别

pivot_wider 问题“`values_from` 中的值不是唯一标识的;输出将包含 list-cols”

优化 expand/pivot_wider R 以标记时间段的所有月份

LeetCode下一个排列与全排列问题

排列oj