Как рассчитать значения, разделенные точкой с запятой внутри ячейки? - PullRequest
1 голос
/ 06 января 2020

У меня есть таблица, которая выглядит следующим образом:

> head(dt)
               variant_id           transcript_id        HH     HNL  NLNL
1: chr10_60842447_A_G_b38 chr10_60871326_60871443 32968;685 1440;20 337;1
2: chr10_60846892_G_A_b38 chr10_60871326_60871443 33157;690 1251;15 337;1
3: chr10_60847284_C_T_b38 chr10_60871326_60871443 33157;690 1251;15 337;1
4: chr10_60849980_T_C_b38 chr10_60871326_60871443 33157;690 1251;15 337;1
5: chr10_60850566_A_T_b38 chr10_60871326_60871443 33157;690 1251;15 337;1
6: chr10_60852394_C_A_b38 chr10_60871326_60871443 33157;690 1251;15 337;1

Я хотел бы взять значения в столбце HH и разделить числа перед точкой с запятой на числа после точки -двоеточие. Например, для первой строки я хотел бы сделать 32968/685 (что будет 48.13). Затем я хотел бы сделать то же самое для значений в столбце NLNL (то есть для первой строки, которая будет 337), а затем я бы хотел вычесть значение, найденное из столбца HH, из значения в столбец NLNL, поэтому 337-48.13 = 228.87. Затем я хотел бы взять это значение вместо нового столбца с именем diff для всех строк.

Как бы я go сделал это? Я могу довольно легко понять, как разделить значения одного столбца на другой и поместить результат в новый столбец, но я не знаю, как извлечь значения, разделенные точкой с запятой, изнутри ячейки и манипулировать ими.

Ответы [ 4 ]

3 голосов
/ 06 января 2020

Один из вариантов - split на ; с strsplit, преобразование в numeric и деление первого элемента на второй

dt[, new := unlist(lapply(strsplit(HH, ";"), 
        function(x) as.numeric(x[1])/as.numeric(x[2])))]

Или другой вариант - чтение столбца как data.table с fread и затем деление

dt[, new := fread(text = .SD[["HH"]], sep=";")[, V1/V2]]

Для нескольких столбцов укажите столбцы в .SDcols, l oop над столбцами и сделайте то же самое

dt[, paste0("new", 1:3) := lapply(.SD, function(x) 
         fread(text = x, sep=";")[, V1/V2]), .SDcols = HH:NLNL]
dt
#               variant_id           transcript_id        HH     HNL  NLNL     new1 new2 new3
#1: chr10_60842447_A_G_b38 chr10_60871326_60871443 32968;685 1440;20 337;1 48.12847 72.0  337
#2: chr10_60846892_G_A_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362 83.4  337
#3: chr10_60847284_C_T_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362 83.4  337
#4: chr10_60849980_T_C_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362 83.4  337
#5: chr10_60850566_A_T_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362 83.4  337
#6: chr10_60852394_C_A_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362 83.4  337

Или опция с tidyverse

library(dplyr)
library(tidyr)
dt %>%
    mutate(rn = row_number()) %>% 
    separate_rows(HH, HNL, NLNL, convert = TRUE) %>% 
    group_by(rn, variant_id, transcript_id) %>% 
    summarise_at(vars(HH:NLNL), ~ first(.)/last(.)) %>%
    ungroup %>% 
    select(-rn)
# A tibble: 6 x 5
#  variant_id             transcript_id              HH   HNL  NLNL
#  <chr>                  <chr>                   <dbl> <dbl> <dbl>
#1 chr10_60842447_A_G_b38 chr10_60871326_60871443  48.1  72     337
#2 chr10_60846892_G_A_b38 chr10_60871326_60871443  48.1  83.4   337
#3 chr10_60847284_C_T_b38 chr10_60871326_60871443  48.1  83.4   337
#4 chr10_60849980_T_C_b38 chr10_60871326_60871443  48.1  83.4   337
#5 chr10_60850566_A_T_b38 chr10_60871326_60871443  48.1  83.4   337
#6 chr10_60852394_C_A_b38 chr10_60871326_60871443  48.1  83.4   337

Это также может быть сделано компактно с

library(purrr)
library(dplyr)# v 0.8.99.9000
dt %>%
     mutate(across(HH:NLNL, ~ fread(text = ., sep=";") %>% 
                      reduce(`/`)))
#              variant_id           transcript_id       HH  HNL NLNL
#1 chr10_60842447_A_G_b38 chr10_60871326_60871443 48.12847 72.0  337
#2 chr10_60846892_G_A_b38 chr10_60871326_60871443 48.05362 83.4  337
#3 chr10_60847284_C_T_b38 chr10_60871326_60871443 48.05362 83.4  337
#4 chr10_60849980_T_C_b38 chr10_60871326_60871443 48.05362 83.4  337
#5 chr10_60850566_A_T_b38 chr10_60871326_60871443 48.05362 83.4  337
#6 chr10_60852394_C_A_b38 chr10_60871326_60871443 48.05362 83.4  337

данными

dt <- structure(list(variant_id = c("chr10_60842447_A_G_b38", 
      "chr10_60846892_G_A_b38", 
"chr10_60847284_C_T_b38", "chr10_60849980_T_C_b38", "chr10_60850566_A_T_b38", 
"chr10_60852394_C_A_b38"), transcript_id = c("chr10_60871326_60871443", 
"chr10_60871326_60871443", "chr10_60871326_60871443", "chr10_60871326_60871443", 
"chr10_60871326_60871443", "chr10_60871326_60871443"), HH = c("32968;685", 
"33157;690", "33157;690", "33157;690", "33157;690", "33157;690"
), HNL = c("1440;20", "1251;15", "1251;15", "1251;15", "1251;15", 
"1251;15"), NLNL = c("337;1", "337;1", "337;1", "337;1", "337;1", 
"337;1")), class = c("data.table", "data.frame"), row.names = c(NA, 
-6L))
2 голосов
/ 06 января 2020

Вот еще один вариант. Мы разделяем данные во вложенной ячейке, а затем отображаем значения.

library(tidyverse)

dt %>%
  mutate_at(vars(HH:NLNL), list(~str_split(., ";") )) %>%
  mutate_at(vars(HH:NLNL), list(~map_dbl(., ~as.numeric(.x) %>% {.[[1]]/.[[2]]}))) 

#>   variant_id             transcript_id              HH   HNL  NLNL
#>   <chr>                  <chr>                   <dbl> <dbl> <dbl>
#> 1 chr10_60842447_A_G_b38 chr10_60871326_60871443  48.1  72     337
#> 2 chr10_60846892_G_A_b38 chr10_60871326_60871443  48.1  83.4   337
#> 3 chr10_60847284_C_T_b38 chr10_60871326_60871443  48.1  83.4   337
#> 4 chr10_60849980_T_C_b38 chr10_60871326_60871443  48.1  83.4   337
#> 5 chr10_60850566_A_T_b38 chr10_60871326_60871443  48.1  83.4   337
#> 6 chr10_60852394_C_A_b38 chr10_60871326_60871443  48.1  83.4   337

РЕДАКТИРОВАТЬ: все, что вам нужно сделать, чтобы иметь новые переменные, это назвать их в списке:

dt %>%
  mutate_at(vars(HH:NLNL), list(new = ~str_split(., ";") )) %>%
  mutate_at(vars(HH_new:NLNL_new), list(~map_dbl(., ~as.numeric(.x) %>% {.[[1]]/.[[2]]})))

#>   variant_id       transcript_id      HH     HNL   NLNL  HH_new HNL_new NLNL_new
#>   <chr>            <chr>              <chr>  <chr> <chr>  <dbl>   <dbl>    <dbl>
#> 1 chr10_60842447_… chr10_60871326_60… 32968… 1440… 337;1   48.1    72        337
#> 2 chr10_60846892_… chr10_60871326_60… 33157… 1251… 337;1   48.1    83.4      337
#> 3 chr10_60847284_… chr10_60871326_60… 33157… 1251… 337;1   48.1    83.4      337
#> 4 chr10_60849980_… chr10_60871326_60… 33157… 1251… 337;1   48.1    83.4      337
#> 5 chr10_60850566_… chr10_60871326_60… 33157… 1251… 337;1   48.1    83.4      337
#> 6 chr10_60852394_… chr10_60871326_60… 33157… 1251… 337;1   48.1    83.4      337
2 голосов
/ 06 января 2020

Один вариант, включающий dplyr и gsubfn, может быть:

df %>%
 mutate_at(vars(HH, HNL, NLNL), ~ gsubfn("([0-9]+);([0-9]+)", function(x, y) as.numeric(x)/as.numeric(y), .))

             variant_id           transcript_id               HH  HNL NLNL
1 chr10_60842447_A_G_b38 chr10_60871326_60871443 48.1284671532847   72  337
2 chr10_60846892_G_A_b38 chr10_60871326_60871443 48.0536231884058 83.4  337
3 chr10_60847284_C_T_b38 chr10_60871326_60871443 48.0536231884058 83.4  337
4 chr10_60849980_T_C_b38 chr10_60871326_60871443 48.0536231884058 83.4  337
5 chr10_60850566_A_T_b38 chr10_60871326_60871443 48.0536231884058 83.4  337
6 chr10_60852394_C_A_b38 chr10_60871326_60871443 48.0536231884058 83.4  33
1 голос
/ 06 января 2020

Вот базовое решение R, использующее strsplit для обработки значений, разделенных точкой с запятой в ячейке:

df <- cbind(df,`colnames<-`(sapply(c("HH","HNL","NLNL"),
                             function(v) sapply(strsplit(df[,v],split = ";"),
                                                function(x) Reduce("/",as.numeric(x)))),c("HHnew","HNLnew","NLNLnew")))
df$diff <- with(df,NLNLnew - HHnew)

, таких что

> df
              variant_id           transcript_id        HH     HNL  NLNL    HHnew HNLnew NLNLnew     diff
1 chr10_60842447_A_G_b38 chr10_60871326_60871443 32968;685 1440;20 337;1 48.12847   72.0     337 288.8715
2 chr10_60846892_G_A_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362   83.4     337 288.9464
3 chr10_60847284_C_T_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362   83.4     337 288.9464
4 chr10_60849980_T_C_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362   83.4     337 288.9464
5 chr10_60850566_A_T_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362   83.4     337 288.9464
6 chr10_60852394_C_A_b38 chr10_60871326_60871443 33157;690 1251;15 337;1 48.05362   83.4     337 288.9464

DATA

df <- structure(list(variant_id = c("chr10_60842447_A_G_b38", "chr10_60846892_G_A_b38", 
"chr10_60847284_C_T_b38", "chr10_60849980_T_C_b38", "chr10_60850566_A_T_b38", 
"chr10_60852394_C_A_b38"), transcript_id = c("chr10_60871326_60871443", 
"chr10_60871326_60871443", "chr10_60871326_60871443", "chr10_60871326_60871443", 
"chr10_60871326_60871443", "chr10_60871326_60871443"), HH = c("32968;685", 
"33157;690", "33157;690", "33157;690", "33157;690", "33157;690"
), HNL = c("1440;20", "1251;15", "1251;15", "1251;15", "1251;15", 
"1251;15"), NLNL = c("337;1", "337;1", "337;1", "337;1", "337;1", 
"337;1")), class = "data.frame", row.names = c(NA, -6L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...