dplyr: как сделать pivot_wider с несколькими столбцами, одновременно создавая новые ковариаты?

#r #dataframe #dplyr #pivot

Вопрос:

В настоящее время у меня есть набор данных протеомики с ~60 столбцами (пациенты и информация, такая как названия белков) и ~1800 строками (конкретные белки).

Мне нужно преобразовать формат из длинного в широкий, чтобы каждая строка соответствовала пациентам, а все столбцы представляли белки. Я могу выполнять (очень) простые преобразования, но в этом примере много столбцов, и, кроме того, требуется некоторое управление данными, поскольку необходимо создавать/извлекать новые ковариаты из исходных данных протеомики, приведенных ниже. Я просто не знаю, как действовать, и не нашел никаких решений, просматривая множество доступных пошаговых инструкций по преобразованию больших наборов данных, подобных этому.

Я предпочитаю dplyr -входные данные, подсказки или решения.

Исходные данные протеомного программного обеспечения выглядят примерно так:

 > head(Heat_BT)
# A tibble: 11 x 6
   protein                                        gene   Intensity_10 Intensity_11 Intensity_MB_1 Intensity_Ref1
   <chr>                                          <chr>  <chr>        <chr>        <chr>          <chr>         
 1 NA                                             NA     Bruschi      Bruschi      Reichl         Reichl        
 2 NA                                             NA     Ctrl         Ctrl         Tumor          Ctrl          
 3 NA                                             NA     Hydro        Hydro        Malignant      Hydro         
 4 NA                                             NA     Ctrl         Ctrl         MB             Ctrl          
 5 von Willebrand factor                          VWF    0.674627721  0.255166769  0.970489979    0.215972215   
 6 Sex hormone-binding globulin                   SHBG   0.516914487  0.476843655  0.88173753     0.306484252   
 7 Glyceraldehyde-3-phosphate dehydrogenase       GAPDH  0.622163594  0.231107563  0.71856463     0.204625234   
 8 Nestin                                         NES    0.868476391  0.547319174  0.832109928    0.440162212   
 9 Heat shock 70 kDa protein 13                   HSPA13 0.484973907  0.435322136  0.539334834    0.28678757    
10 Isocitrate dehydrogenase [NADP], mitochondrial IDH2   1.017596364  0.107395157  0.710225344    0.251976997   
11 Mannan-binding lectin serine protease 1        MASP1  0.491321206  0.434995681  0.812500775    0.403583705   
 

Ожидаемый результат:

               id     lab malig      diag       VWF      SHBG     GAPDH       NES    HSPA13      IDH2     MASP1
1   Intensity_10 Bruschi  Ctrl     Hydro 0.6746277 0.5169145 0.6221636 0.8684764 0.4849739 1.0175964 0.4913212
2   Intensity_11 Bruschi  Ctrl     Hydro 0.2551668 0.4768437 0.2311076 0.5473192 0.4353221 0.1073952 0.4349957
3 Intensity_MB_1  Reichl Tumor Malignant 0.9704900 0.8817375 0.7185646 0.8321099 0.5393348 0.7102253 0.8125008
4 Intensity_Ref1  Reichl  Ctrl     Hydro 0.2159722 0.3064843 0.2046252 0.4401622 0.2867876 0.2519770 0.4035837
 
  • Программное обеспечение proteomic автоматически выводит первые четыре строки в виде категорий, к которым относится каждый пациент.

На основе этих первых четырех строк:

  • В широкий формат необходимо добавить четыре новые ковариаты: (1) Heat_BT$id соответствуют названию исследования каждого пациента, (2) Heat_BT$lab соответствуют тому, в какой лаборатории были получены данные, (3) Heat_BT$malig соответствуют ли случай пациента контрольному случаю или случаю опухоли и, наконец, (4) Heat_BT$diag соответствуют основному диагнозу.

Данные

 Heat_BT <- structure(list(protein = c(NA, NA, NA, NA, "von Willebrand factor", 
                           "Sex hormone-binding globulin", "Glyceraldehyde-3-phosphate dehydrogenase", 
                           "Nestin", "Heat shock 70 kDa protein 13", "Isocitrate dehydrogenase [NADP], mitochondrial", 
                           "Mannan-binding lectin serine protease 1"), gene = c(NA, NA, 
                                                                                NA, NA, "VWF", "SHBG", "GAPDH", "NES", "HSPA13", "IDH2", "MASP1"
                           ), Intensity_10 = c("Bruschi", "Ctrl", "Hydro", "Ctrl", "0.674627721", 
                                               "0.516914487", "0.622163594", "0.868476391", "0.484973907", "1.017596364", 
                                               "0.491321206"), Intensity_11 = c("Bruschi", "Ctrl", "Hydro", 
                                                                                "Ctrl", "0.255166769", "0.476843655", "0.231107563", "0.547319174", 
                                                                                "0.435322136", "0.107395157", "0.434995681"), Intensity_MB_1 = c("Reichl", 
                                                                                                                                                 "Tumor", "Malignant", "MB", "0.970489979", "0.88173753", "0.71856463", 
                                                                                                                                                 "0.832109928", "0.539334834", "0.710225344", "0.812500775"), 
               Intensity_Ref1 = c("Reichl", "Ctrl", "Hydro", "Ctrl", "0.215972215", 
                                  "0.306484252", "0.204625234", "0.440162212", "0.28678757", 
                                  "0.251976997", "0.403583705")), row.names = c(NA, -11L), class = c("tbl_df", 
                                                                                                     "tbl", "data.frame"))
 

Ответ №1:

Вот dplyr решение для вас. Это два шага, так как сначала вам нужно будет собрать intensity переменные.

 Heat_BT <- Heat_BT %>% na.exclude()

Heat_BT[,-1] %>% pivot_longer(
        cols = Intensity_10:Intensity_Ref1,
        names_to = "id"
) %>% pivot_wider(
        names_from = gene
) %>% mutate(
        across(.cols = -"id", as.numeric)
)
 

Что дает следующее output

 # A tibble: 4 x 8
  id             VWF         SHBG        GAPDH       NES         HSPA13      IDH2        MASP1      
  <chr>          <chr>       <chr>       <chr>       <chr>       <chr>       <chr>       <chr>      
1 Intensity_10   0.674627721 0.516914487 0.622163594 0.868476391 0.484973907 1.017596364 0.491321206
2 Intensity_11   0.255166769 0.476843655 0.231107563 0.547319174 0.435322136 0.107395157 0.434995681
3 Intensity_MB_1 0.970489979 0.88173753  0.71856463  0.832109928 0.539334834 0.710225344 0.812500775
4 Intensity_Ref1 0.215972215 0.306484252 0.204625234 0.440162212 0.28678757  0.251976997 0.403583705
 

У меня возникли проблемы с видением связи между variables тем , что вы хотели добавить из data , поэтому я предположил, что, как только вы сможете pivot правильно ввести свои данные, вы сможете заполнить остальные.

Я с радостью пересмотрю свой ответ, если вы сможете более ясно объяснить, как связаны эти переменные.

Лучшие

ПРАВКА: Обратите внимание, что я удалил первые четыре строки из data , так как я не сразу увидел связь между переменными, которые вы хотели добавить.

ПРАВКА 2: Я предположил , что первые 3 строки являются ковариатами, которые вы хотите добавить, чтобы первая строка была lab malig и diag соответственно.

 # Extract the relevant information
# from the data.
id_cols <- bind_cols(
        var = c("lab", "malig", "diag"),
        Heat_BT[1:3,-c(1,2)] 
) %>% group_by(var) %>% pivot_longer(
        cols = Intensity_10:Intensity_Ref1, names_to = "id"
) %>% pivot_wider(
        names_from = var,
)
        
        
# Remove these identifiers;
Heat_BT <- Heat_BT %>% na.exclude() 

# Pivot the table;
pivoted_table <- Heat_BT[,-1] %>% pivot_longer(
        cols = Intensity_10:Intensity_Ref1,names_to = "id"
) %>% pivot_wider(
        names_from = gene,
) %>% mutate(
        across(.cols = -"id", as.numeric)
        )

# Join with the ID colums
left_join(
        id_cols,
        pivoted_table
)
 

Что дает output ,

 # A tibble: 4 x 11
  id             lab     malig diag      VWF         SHBG        GAPDH       NES         HSPA13      IDH2        MASP1      
  <chr>          <chr>   <chr> <chr>     <chr>       <chr>       <chr>       <chr>       <chr>       <chr>       <chr>      
1 Intensity_10   Bruschi Ctrl  Hydro     0.674627721 0.516914487 0.622163594 0.868476391 0.484973907 1.017596364 0.491321206
2 Intensity_11   Bruschi Ctrl  Hydro     0.255166769 0.476843655 0.231107563 0.547319174 0.435322136 0.107395157 0.434995681
3 Intensity_MB_1 Reichl  Tumor Malignant 0.970489979 0.88173753  0.71856463  0.832109928 0.539334834 0.710225344 0.812500775
4 Intensity_Ref1 Reichl  Ctrl  Hydro     0.215972215 0.306484252 0.204625234 0.440162212 0.28678757  0.251976997 0.403583705
 

Это будет работать с имеющимися у вас данными, независимо от их размера. Очевидно, что вы можете сделать подход более пуленепробиваемым, заменив, например, cols = Intensity_10:Intensity_Ref1 на contains("intensity") .

Правка 3

У вас намного больше переменных, чем указано здесь, поэтому, когда вы pivot их не изменяете во время pivot процесса.

Таким образом, мы можем использовать более надежный подход, предполагая, что все variables не представленные здесь данные аналогичны приведенным, соответствующим образом изменив cols аргумент.

 # Extract the relevant information
# from the data.
id_cols <- bind_cols(
        var = c("lab", "malig", "diag"),
        Heat_BT[1:3,-c(1,2)] 
) %>% group_by(var) %>% pivot_longer(
        cols = -"var", names_to = "id"
) %>% pivot_wider(
        names_from = var,
)


# Remove these identifiers;
Heat_BT <- Heat_BT[-(1:4),]

# Pivot the table;
pivoted_table <- Heat_BT[,-1] %>% pivot_longer(
        cols = -"gene",
        names_to = "id"
) %>% pivot_wider(
        names_from = gene,
) %>% mutate(
        across(.cols = -"id", as.numeric)
)

# Join with the ID colums
left_join(
        id_cols,
        pivoted_table
)
 

Что дает тот же результат, что и выше.

Комментарии:

1. Привет @Serkan, большое вам спасибо за это решение. Все значения в выходных данных EDIT 2 as.character следующие . Есть ли простой способ убедиться, что все значения в выходных данных являются as.numeric ?

2. Вы можете добавить values_fn = as.numeric pivot_wider , но лично я бы сделал это mutate после того, как у вас будет желаемый результат!

3. Интересный. Отображается ли эта ошибка в ваших собственных данных или она также отображается в предоставленных вами образцах данных? Вы можете это проверить, пожалуйста?

4. Я изменю свой ответ, и если это не сработает, мы сможем рассмотреть альтернативные решения. Все остальные переменные аналогичны тем, которые вы указали здесь, да? Все они должны быть numeric переменными, да?

5. Хорошо, я изменил свой ответ. Дай мне знать, как все прошло. Помните , что решение предполагает, что первые четыре строки не нужны для чего-либо, кроме создания lab , malig и diag .

Ответ №2:

Вы могли бы сделать:

 Heat_BT[,2][1:3] <- c('lab', 'malig', 'diag')
data.table::transpose(Heat_BT[,-1],keep.names = 'gene',make.names = TRUE)

            gene     lab malig      diag   NA         VWF        SHBG       GAPDH         NES      HSPA13        IDH2       MASP1
1   Intensity_10 Bruschi  Ctrl     Hydro Ctrl 0.674627721 0.516914487 0.622163594 0.868476391 0.484973907 1.017596364 0.491321206
2   Intensity_11 Bruschi  Ctrl     Hydro Ctrl 0.255166769 0.476843655 0.231107563 0.547319174 0.435322136 0.107395157 0.434995681
3 Intensity_MB_1  Reichl Tumor Malignant   MB 0.970489979  0.88173753  0.71856463 0.832109928 0.539334834 0.710225344 0.812500775
4 Intensity_Ref1  Reichl  Ctrl     Hydro Ctrl 0.215972215 0.306484252 0.204625234 0.440162212  0.28678757 0.251976997 0.403583705
 

Комментарии:

1. Привет @Onyambu, большое вам спасибо за ваш вклад. Я получаю сообщение об ошибке при попытке запустить ваш скрипт: > Heat_BT[,2][1:3] <- c('lab', 'malig', 'diag') выдает следующее: Ошибка: Назначенные данные `c(«лаборатория», «малиг», «diag») должны быть совместимы с существующими данными. x Существующие данные содержат 1811 строк. x Назначенные данные содержат 3 строки. ℹ Перерабатываются только векторы размера 1. Знаете ли вы, как это можно исправить?