Как преобразовать символьный столбец с «0/0» в числовой - PullRequest
0 голосов
/ 07 октября 2019

У меня есть фрейм данных, и все столбцы классифицируются как символы. Каждый столбец содержит дробь. Я хочу преобразовать столбцы в целые числа, но некоторые столбцы имеют дробь "0/0", что, похоже, не нравится R. Я попробовал следующее, но получил

df2 <- as.numeric(df)

и получил следующее

Error: (list) object cannot be coerced to type 'double'

Мне не удалось найти сообщение, объясняющее, как преобразовать символ, содержащий дробь "0/0 "к числовому значению 0. Я понимаю, что есть причина, по которой R доставляет мне проблемы со всем делением на ноль. Я просто имею дело с генетическими данными, и гораздо проще преобразовать данные в числовые и сложить все, чем выполнять какую-то функцию замены. Фактический фрейм данных - это десятки миллионов строк и более 500 строк.

Вот пример фрейма данных

df <- structure(list(`GEN[5].GT` = c("0/1", "0/0", "0/0", "0/0", 
 "0/1", "0/0", "0/0", "1/1", "0/0", "0/0"), `GEN[1].GT` = c("0/0", 
 "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0"
 ), `GEN[6].GT` = c("1/1", "0/0", "0/0", "0/0", "0/0", "0/0", 
 "0/1", "0/0", "0/0", "0/0"), `GEN[9].GT` = c("0/0", "0/0", 
 "0/0", "0/0", "0/1", "0/0", "0/0", "0/1", "0/0", "0/0"), `GEN[89].GT` = c("0/0", 
 "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0"
 ), `GEN[453].GT` = c("0/0", "0/0", "0/1", "0/0", "0/0", "0/0", 
 "0/0", "0/0", "0/0", "0/0"), `GEN[554].GT` = c("0/0", "0/0", 
 "0/0", "0/0", "0/0", "0/0", "1/1", "0/0", "0/0", "0/0"), `GEN[9864].GT` = c("0/0", 
 "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0", "0/0"
 ), `GEN[1234].GT` = c("1/1", "0/0", "0/0", "0/0", "0/0", "0/0", 
 "0/0", "0/0", "0/0", "0/0"), `GEN[3333].GT` = c("0/0", "0/0", 
 "0/0", "0/0", "0/0", "1/1", "0/0", "0/1", "0/0", "0/0")), row.names = c(NA, 
 10L), class = "data.frame")

# Expected output
 df2 <- structure(list(`GEN[5].GT` = c("0.5", "0", "0", "0", 
 "0.5", "0", "0", "1", "0", "0"), `GEN[1].GT` = c("0", 
 "0", "0", "0", "0", "0", "0", "0", "0", "0"
 ), `GEN[6].GT` = c("1", "0", "0", "0", "0", "0", 
 "0.5", "0", "0", "0"), `GEN[9].GT` = c("0", "0", 
 "0", "0", "0.5", "0", "0", "0.5", "0", "0"), `GEN[89].GT` = c("0", 
 "0", "0", "0", "0", "0", "0", "0", "0", "0"
 ), `GEN[453].GT` = c("0", "0", "0.5", "0", "0", "0", 
 "0", "0", "0", "0"), `GEN[554].GT` = c("0", "0", 
 "0", "0", "0", "0", "1", "0", "0", "0"), `GEN[9864].GT` = c("0", 
 "0", "0", "0", "0", "0", "0", "0", "0", "0"
 ), `GEN[1234].GT` = c("1", "0", "0", "0", "0", "0", 
 "0", "0", "0", "0"), `GEN[3333].GT` = c("0", "0", 
 "0", "0", "0", "1", "0", "0.5", "0", "0")), row.names = c(NA, 
 10L), class = "data.frame")

Ответы [ 2 ]

2 голосов
/ 07 октября 2019

Мы можем использовать gsub, чтобы захватить две стороны и поместить их в скобки, заменить / на +, а затем разделить на 2.

library(dplyr)
df %>% 
   rowwise() %>% 
   #try mutate_all(~gsub('(.*)/(.*)','(\\1+\\2)/2',.)) to see the underlying formula 
   mutate_all(~eval(parse(text=gsub('(.*)/(.*)','(\\1+\\2)/2',.))))  %>% 
   ungroup()

# A tibble: 10 x 10
   `GEN[5].GT` `GEN[1].GT` `GEN[6].GT` `GEN[9].GT` `GEN[89].GT` `GEN[453].GT` `GEN[554].GT` `GEN[9864].GT` `GEN[1234].GT`
         <dbl>       <dbl>       <dbl>       <dbl>        <dbl>         <dbl>         <dbl>          <dbl>          <dbl>
 1         0.5           0         1           0              0           0               0              0              1
 2         0             0         0           0              0           0               0              0              0
 3         0             0         0           0              0           0.5             0              0              0
 4         0             0         0           0              0           0               0              0              0
 5         0.5           0         0           0.5            0           0               0              0              0
 6         0             0         0           0              0           0               0              0              0
 7         0             0         0.5         0              0           0               1              0              0
 8         1             0         0           0.5            0           0               0              0              0
 9         0             0         0           0              0           0               0              0              0
10         0             0         0           0              0           0               0              0              0
# ... with 1 more variable: `GEN[3333].GT` <dbl>
2 голосов
/ 07 октября 2019

Мы можем создать столбец с именами строк (rownames_to_column из tibble), а затем разделить каждый столбец с разделителем (/) с помощью separate_rows, а convert автоматически с типом, сгруппированным по 'rn'получите mean каждого из столбцов

library(dplyr)
library(tibble)
library(tidyr)
df %>%
   rownames_to_column('rn') %>%
   separate_rows(-1, convert = TRUE) %>%
   group_by(rn) %>% 
   summarise_all(mean) %>%
   select(-rn)
# A tibble: 10 x 10
#   `GEN[5].GT` `GEN[1].GT` `GEN[6].GT` `GEN[9].GT` `GEN[89].GT` `GEN[453].GT` `GEN[554].GT` `GEN[9864].GT` `GEN[1234].GT` `GEN[3333].GT`
#         <dbl>       <dbl>       <dbl>       <dbl>        <dbl>         <dbl>         <dbl>          <dbl>          <dbl>          <dbl>
# 1         0.5           0         1           0              0           0               0              0              1            0  
# 2         0             0         0           0              0           0               0              0              0            0  
# 3         0             0         0           0              0           0               0              0              0            0  
# 4         0             0         0           0              0           0.5             0              0              0            0  
# 5         0             0         0           0              0           0               0              0              0            0  
# 6         0.5           0         0           0.5            0           0               0              0              0            0  
# 7         0             0         0           0              0           0               0              0              0            1  
# 8         0             0         0.5         0              0           0               1              0              0            0  
# 9         1             0         0           0.5            0           0               0              0              0            0.5
#10         0             0         0           0              0           0               0              0              0            0  

или другой вариант, как @IceCreamToucan упомянул в комментариях, чтобы разделить ячейки с strsplit и взять mean

library(purrr)    
df %>% 
   mutate_all(~ map_dbl(strsplit(., '/'), ~ mean(as.numeric(.))))

Или другой вариант, возможно, более эффективный (в base R) - передать именованный вектор, заменить значения на совпадения

nm1 <- setNames(c(0, 0.5, 0.5, 1), c("0/0", "1/0", "0/1", "1/1"))
df[] <- lapply(df, function(x) nm1[x])
df
#   GEN[5].GT GEN[1].GT GEN[6].GT GEN[9].GT GEN[89].GT GEN[453].GT GEN[554].GT GEN[9864].GT GEN[1234].GT GEN[3333].GT
#1        0.5         0       1.0       0.0          0         0.0           0            0            1          0.0
#2        0.0         0       0.0       0.0          0         0.0           0            0            0          0.0
#3        0.0         0       0.0       0.0          0         0.5           0            0            0          0.0
#4        0.0         0       0.0       0.0          0         0.0           0            0            0          0.0
#5        0.5         0       0.0       0.5          0         0.0           0            0            0          0.0
#6        0.0         0       0.0       0.0          0         0.0           0            0            0          1.0
#7        0.0         0       0.5       0.0          0         0.0           1            0            0          0.0
#8        1.0         0       0.0       0.5          0         0.0           0            0            0          0.5
#9        0.0         0       0.0       0.0          0         0.0           0            0            0          0.0
#10       0.0         0       0.0       0.0          0         0.0           0            0            0          0.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...