将 DataTable 结构自定义为 List

Customize DataTable structure to a List

我打算转置数据table DT_in 以便列 indv1, ... 应该是行,POS 应该是列。因此,对于每个 indv,都会有一个来自 POS 行的命名列,其中包含相应的值(1,2 和 0)。我实际上可以通过 tidyr::pivot 函数来管理这部分。问题是,我需要为列 ID 中的每组 ID 完成整个工作。因此输出将是一个列表,因此对于 ID 中的每组 ID 作为列表的第一个元素,转置后的 table 将是一个子列表。

> DT_in
CHR      POS          ID         indv1  indv2  indv3  
1   31439_T_A   ENSG00000232325     1    1    2
1   31504_G_A   ENSG00000242474     2    1    1
1   34713_A_C   ENSG00000242474     1    0    1
1   34918_C_T   ENSG00000242474     1    0    1
1   35119_G_A   ENSG00000239715     0    0    1

我尝试了什么:

DT_in %>% 
  group_by(ID) %>% 
  pivot_longer(
  cols = starts_with("indv")
)

View(DT_in)
  CHR POS       ID              name  value
 <dbl> <chr>     <chr>           <chr> <dbl>
 1     1 31439_T_A ENSG00000232325 indv1     1
 2     1 31439_T_A ENSG00000232325 indv2     1
 3     1 31439_T_A ENSG00000232325 indv3     2
 4     1 31504_G_A ENSG00000242474 indv1     2
 5     1 31504_G_A ENSG00000242474 indv2     1
 6     1 31504_G_A ENSG00000242474 indv3     1
 7     1 34713_A_C ENSG00000242474 indv1     1
 8     1 34713_A_C ENSG00000242474 indv2     0
 9     1 34713_A_C ENSG00000242474 indv3     1
10     1 34918_C_T ENSG00000242474 indv1     1
11     1 34918_C_T ENSG00000242474 indv2     0
12     1 34918_C_T ENSG00000242474 indv3     1
13     1 35119_G_A ENSG00000239715 indv1     0
14     1 35119_G_A ENSG00000239715 indv2     0
15     1 35119_G_A ENSG00000239715 indv3     1

pivot_wider(pivot, names_from = POS, values_from = value)

Error: Internal error in `compact_rep()`: Negative `n` in `compact_rep()`.
Run `rlang::last_error()` to see where the error occurred.
In addition: Warning message:
In nrow * ncol : NAs produced by integer overflow

当我想在不构建列表的情况下完成工作时出现的错误,也是因为 POS 列中的行数对于 ID 列中的每个 ID 都不相同.这就是为什么我认为它应该作为一个列表来完成。

更新: 期望的输出:

> DF_OUT1
CHR        ID       name    31439_T_A
 1 ENSG00000232325 indv1     1         
 1 ENSG00000232325 indv2     1 
 1 ENSG00000232325 indv3     2 

> DF_OUT2
CHR        ID       name    31504_G_A     34713_A_C    34918_C_T
 1 ENSG00000242474 indv1     2                 1           1
 1 ENSG00000242474 indv2     1                 0           0
 1 ENSG00000242474 indv3     1                 1           1

> DF_OUT3
CHR        ID       name    35119_G_A
 1 ENSG00000239715 indv1     0         
 1 ENSG00000239715 indv2     0 
 1 ENSG00000239715 indv3     1

正如所见,我需要通过提供单独数据帧的循环或在由每个唯一 ID 命名的元素列表中单独存储每个 ID 的输出。

split 函数根据函数或变量将 data.frame 吐出到列表中。我们可以将您的 data.frame 转换为长格式,根据 ID 将其拆分为数据帧列表,然后使用 lapply 再次将它们转换为宽格式以获得 data.frame 的列表小号:

library(tidyverse)
df %>%
    pivot_longer(starts_with('indv')) %>%
    split(.$ID) %>%
    lapply(., function(x) pivot_wider(x, names_from = 'POS'))

$ENSG00000232325
# A tibble: 3 × 4
    CHR ID              name  `31439_T_A`
  <int> <chr>           <chr>       <int>
1     1 ENSG00000232325 indv1           1
2     1 ENSG00000232325 indv2           1
3     1 ENSG00000232325 indv3           2

$ENSG00000239715
# A tibble: 3 × 4
    CHR ID              name  `35119_G_A`
  <int> <chr>           <chr>       <int>
1     1 ENSG00000239715 indv1           0
2     1 ENSG00000239715 indv2           0
3     1 ENSG00000239715 indv3           1

$ENSG00000242474
# A tibble: 3 × 6
    CHR ID              name  `31504_G_A` `34713_A_C` `34918_C_T`
  <int> <chr>           <chr>       <int>       <int>       <int>
1     1 ENSG00000242474 indv1           2           1           1
2     1 ENSG00000242474 indv2           1           0           0
3     1 ENSG00000242474 indv3           1           1           1

对于一些额外的上下文,这里解释了为什么我们在使用管道时需要在拆分中将 ID 列称为 .$IDWhy dot in base::split(.$cyl)?