#r #na #csv
#r #na #csv
Вопрос:
Мой набор данных выглядит следующим образом:
id Protein IDs Coverage [%] Coverage2 [%] Max
0 A0A075B6I0 14.8 20.49 20.49
1 A0A075B6I9;P04211 21.4 NA;NA
2 A0A075B6J9 24.6 24.58;22.48 24.58
3 A0A075B6K4 28.7 NA
4 A0A075B6K2;A0A075B6K5 49.6 44.22;NA 44.22
В столбце Max
я пытаюсь получить максимальное значение между всеми значениями в «Coverage2 [%]», используя следующий код:
dt$Max <- sapply(strsplit(as.character(dt$`Coverage2 [%]`),";"), function(x) ifelse( !all(is.na(x)), max(as.numeric(x), na.rm=T), NA) )
Но, как можно видеть в разделе данных выше, если есть NA
только один или несколько NA
s, я ничего не получаю, в то время как желаемый результат будет одним NA
(в обоих случаях). Предположим, что dt
это приведенный выше набор данных без столбца Max.
Что я делаю не так, пожалуйста? Следует отметить, что я получаю следующие две ошибки в консоли: Warning in ifelse(!all(is.na(x)), max(as.numeric(x), na.rm = T), NA) : NAs introduced by coercion
и Warning in max(as.numeric(x), na.rm = T) : no non-missing arguments to max; returning -Inf
Ответ №1:
Мы можем использовать separate_rows
with convert = TRUE
from tidyr
для разделения столбца, а также для изменения типа, затем выполнить группировку по max
и либо выполнить a right_join
, либо использовать bind_cols
для создания столбца в исходных данных
library(dplyr)
library(tidyr)
dt %>%
separate_rows(`Coverage2 [%]`, convert = TRUE) %>%
group_by(id) %>%
summarise(Max = if(all(is.na(`Coverage2 [%]`))) NA_real_ else
max(`Coverage2 [%]`, na.rm = TRUE), .groups = 'drop') %>%
right_join(dt) %>%
select(names(dt), Max)
-вывод
# A tibble: 5 x 5
# id `Protein IDs` `Coverage [%]` `Coverage2 [%]` Max
# <int> <chr> <dbl> <chr> <dbl>
#1 0 A0A075B6I0 14.8 20.49 20.5
#2 1 A0A075B6I9;P04211 21.4 NA;NA NA
#3 2 A0A075B6J9 24.6 24.58;22.48 24.6
#4 3 A0A075B6K4 28.7 <NA> NA
#5 4 A0A075B6K2;A0A075B6K5 49.6 44.22;NA 44.2
В коде OP мы получаем предупреждение, и это можно предотвратить, если мы используем if/else
sapply(strsplit(as.character(dt$`Coverage2 [%]`),";"), function(x) {
x1 <- as.numeric(x)
if(all(is.na(x1))) NA_real_ else max(x1, na.rm = TRUE)
})
#[1] 20.49 NA 24.58 NA 44.22
данные
dt <- structure(list(id = 0:4, `Protein IDs` = c("A0A075B6I0", "A0A075B6I9;P04211",
"A0A075B6J9", "A0A075B6K4", "A0A075B6K2;A0A075B6K5"), `Coverage [%]` = c(14.8,
21.4, 24.6, 28.7, 49.6), `Coverage2 [%]` = c("20.49", "NA;NA",
"24.58;22.48", NA, "44.22;NA")), class = "data.frame", row.names = c(NA,
-5L))