【问题标题】:pivot to wide dataframe with repeating column names转向具有重复列名的宽数据框
【发布时间】:2021-01-15 22:05:43
【问题描述】:

我有一个数据框,我需要为外部程序 (PRISM Graphpad) 进行正确的配置。在这个玩具示例中,我有一个 5x3 条件矩阵,每个条件都有重复测量。最初用于 R 中的绘图和分析,数据采用适当的长整齐格式。

虽然我可以轻松地旋转数据,但在旋转 DF 宽时我遇到了值不唯一的问题。我需要将复制品放在具有相同名称的相邻列中,以便 PRISM 正确识别事物。但是,当我旋转宽时,重复的值会被推到一个列表中,因为它们在 id_cols 中没有唯一标识。

在现实生活的例子中,条件矩阵当然要大得多,重复次数更多(但每个条件的数量相同),除此之外,每个 df 都是列表列中的一个条目,所以我可能需要使用 purrr::map 函数来应用解决方案。

library(tidyverse)
df <- data.frame("ID" = c(rep(LETTERS[seq(1,5)], 2)),
              "cond1" = runif(10, 0, 1),
              "cond2" = runif(10, 1, 10),
              "cond3" = runif(10, 10, 100))


#// original long dataframe
long_df <- pivot_longer(data = df, cols = c("cond1", "cond2", "cond3"))
long_df
#> # A tibble: 30 x 3
#>    ID    name   value
#>    <chr> <chr>  <dbl>
#>  1 A     cond1  0.424
#>  2 A     cond2  9.01 
#>  3 A     cond3 61.6  
#>  4 B     cond1  0.460
#>  5 B     cond2  2.33 
#>  6 B     cond3 40.3  
#>  7 C     cond1  0.107
#>  8 C     cond2  5.82 
#>  9 C     cond3 23.9  
#> 10 D     cond1  0.714
#> # ... with 20 more rows


#// desired output
desired_df <- cbind(df[c(1:5),], df[c(6:10),])
desired_df <- desired_df[,c(1,2,6,3,7,4,8)]
colnames(desired_df)[c(3,5,7)] <- c("cond1", "cond2", "cond3")
desired_df
#>   ID     cond1     cond1    cond2    cond2    cond3    cond3
#> 1  A 0.4244798 0.8078372 9.005544 5.349371 61.61488 73.80651
#> 2  B 0.4596927 0.3509671 2.325029 8.636263 40.33949 66.54288
#> 3  C 0.1069974 0.3903294 5.817079 7.100623 23.87013 99.98683
#> 4  D 0.7144698 0.1005499 9.886948 7.006333 19.40680 66.86696
#> 5  E 0.2903691 0.6177356 8.890734 9.863695 46.56568 66.42537


#// result from pivot_wider
wide_df <- pivot_wider(long_df, id_cols = ID, names_from = name, values_from = value)
#> Warning: Values are not uniquely identified; output will contain list-cols.
#> * Use `values_fn = list` to suppress this warning.
#> * Use `values_fn = length` to identify where the duplicates arise
#> * Use `values_fn = {summary_fun}` to summarise duplicates
wide_df
#> # A tibble: 5 x 4
#>   ID    cond1     cond2     cond3    
#>   <chr> <list>    <list>    <list>   
#> 1 A     <dbl [2]> <dbl [2]> <dbl [2]>
#> 2 B     <dbl [2]> <dbl [2]> <dbl [2]>
#> 3 C     <dbl [2]> <dbl [2]> <dbl [2]>
#> 4 D     <dbl [2]> <dbl [2]> <dbl [2]>
#> 5 E     <dbl [2]> <dbl [2]> <dbl [2]>

reprex package (v0.3.0) 于 2021-01-15 创建 .0)

【问题讨论】:

  • 不建议列名重复
  • 明白。这不是我在 R 中要做的,但我相信这是下游软件将重复正确组合在一起的先决条件。并感谢您的解决方案。显然,我应该使名称唯一,旋转,然后如果需要,我可以简单地更改名称。谢谢!

标签: r tidyverse purrr


【解决方案1】:

不建议使用重复的列名,因此,我们通过附加使用rowid 创建的唯一索引来修改“名称”列,并使用该索引与pivot_wider 进行整形

library(dplyr)
library(tidyr)
library(stringr)
library(data.table)
long_df %>% 
   mutate(name = str_c(name, "_", rowid(ID, name))) %>% 
   pivot_wider(names_from = name, values_from = value, names_sort = TRUE)

-输出

# A tibble: 5 x 7
#  ID    cond1_1 cond1_2 cond2_1 cond2_2 cond3_1 cond3_2
#  <chr>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
#1 A       0.293   0.920    6.44    9.14    18.5    71.9
#2 B       0.225   0.280    4.34    2.78    59.7    16.9
#3 C       0.704   0.764    7.05    1.40    75.3    64.0
#4 D       0.519   0.802    7.06    5.51    22.4    66.7
#5 E       0.663   0.255    3.88    2.25    30.1    14.2

如果它需要有重​​复的名称,只需将名称末尾的_\\d+ 去掉str_remove

【讨论】:

    【解决方案2】:

    试试这个:

    library(tidyverse)
    #Code
    new <- df %>%
      pivot_longer(-1) %>%
      group_by(ID,name) %>%
      mutate(name=paste0(name,'.',row_number())) %>%
      pivot_wider(names_sort = T,names_from=name,values_from=value)
    

    输出:

    # A tibble: 5 x 7
    # Groups:   ID [5]
      ID    cond1.1 cond1.2 cond2.1 cond2.2 cond3.1 cond3.2
      <chr>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
    1 A       0.619   0.851    4.49    9.17    70.9    84.2
    2 B       0.989   0.542    9.64    3.57    55.3    28.3
    3 C       0.594   0.602    5.16    8.97    26.2    19.0
    4 D       0.349   0.244    5.29    8.52    44.8    17.7
    5 E       0.683   0.848    7.27    8.07    97.3    73.9
    

    那么你可以这样处理:

    #Further process
    names(new) <- gsub("\\..*","",names(new))
    

    输出:

    # A tibble: 5 x 7
    # Groups:   ID [5]
      ID    cond1 cond1 cond2 cond2 cond3 cond3
      <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    1 A     0.129 0.360  4.60  2.74  55.3  58.3
    2 B     0.416 0.384  5.93  9.17  15.7  21.8
    3 C     0.724 0.622  9.30  7.81  76.9  79.0
    4 D     0.101 0.951  6.35  1.58  30.3  68.5
    5 E     0.238 0.814  9.46  9.50  12.4  57.8
    

    并导出为 .txt 供其他软件使用。

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 2015-07-02
      • 2020-11-12
      • 1970-01-01
      • 1970-01-01
      • 2020-07-14
      相关资源
      最近更新 更多