#r #dplyr #data.table #max #min
#r #dplyr #данные.таблица #макс #минимум
Вопрос:
У меня есть набор данных, в котором я сгруппирован по Gene
столбцу. Некоторые значения сгруппированы в каждой строке, .,
поэтому я удаляю их, оставляя только несколько числовых символов в строке и столбце.
Для этого я кодирую:
#Group by Gene:
data <- setDT(df2)[, lapply(.SD, paste, collapse = ", "), by = Genes]
#Remove ., from anywhere in the dataframe
dat <- data.frame(lapply(data, function(x) {
gsub("\.,|\.$|\,$|(, .$)", "", x)
}))
Мои данные до удаления .,
и после группировки Gene
выглядят следующим образом:
Gene col1 col2 col3 col4
ACE 0.3, 0.4, 0.5, 0.5 . ., ., . 1, 1, 1, 1, 1
NOS2 ., . . ., ., ., . 0, 0, 0, 0, 0
BRCA1 . ., . 1, 1, 1, 1, 1
HER2 . 0.1, ., ., 0.2, 0.1 . 1, 1, 1, 1, 1
После удаления .,
моих данных выглядит так:
Gene col1 col2 col3 col4
ACE 0.3, 0.4, 0.5, 0.5 1, 1, 1, 1, 1
NOS2 0, 0, 0, 0, 0
BRCA1 1, 1, 1, 1, 1
HER2 0.1, 0.2, 0.1 1, 1, 1, 1, 1
Сейчас я пытаюсь выбрать минимальное или максимальное значение для строки и столбца.
Ожидаемый пример вывода:
Gene col1 col2 col3 col4
ACE 0.5 1
NOS2 0
BRCA1 1
HER2 0.1 1
#For col1 I need the max value per row (so for ACE 0.5 is selected)
#For col2 I need the min value per row
К сведению, мои фактические данные составляют 100 столбцов и 20 000 строк — для разных столбцов требуются либо максимальные, либо минимальные значения для каждого выбранного гена.
Однако с кодом, который я использую, я получаю только ожидаемый результат col4
, и мои другие столбцы повторяют выбранное значение дважды (я получаю 0.5, 0.5
и 0.1, 0.1
и я не могу понять, почему).
Код, который я использую для выбора минимальных / максимальных значений, является:
#Max value per feature and row
max2 = function(x) if(all(is.na(x))) NA else max(x,na.rm = T)
getmax = function(col) str_extract_all(col,"[0-9\.-] ") %>%
lapply(.,function(x)max2(as.numeric(x)) ) %>%
unlist()
#Min value per feature and row
min2 = function(x) if(all(is.na(x))) NA else min(x,na.rm = T)
getmin = function(col) str_extract_all(col,"[0-9\.-] ") %>%
lapply(.,function(x)min2(as.numeric(x)) ) %>%
unlist()
data <- dt %>%
mutate_at(names(dt)[2],getmax)
data <- dt %>%
mutate_at(names(dt)[3],getmin)
data <- dt %>%
mutate_at(names(dt)[4],getmax)
Почему эти функции выбора не работают для всех моих столбцов? Все столбцы являются классом символов. Мне также интересно, нужно ли мне .,
вообще удалять, и я могу просто перейти прямо к выбору максимального / минимального значения для строки и столбца?
Пример входных данных:
structure(list(Gene = c("ACE", "NOS2", "BRCA1", "HER2"), col1 = c("0.3, 0.4, 0.5, 0.5",
"", "", ""), col2 = c("", "", "", " 0.1, 0.2 0.,1"), col3 = c(NA,
NA, NA, NA), col4 = c(" 1, 1, 1, 1, 1",
" 0, 0, 0, 0, 0", " 1, 1, 1, 1, 1",
" 1, 1, 1, 1, 1")), row.names = c(NA, -4L), class = c("data.table",
"data.frame"))
Комментарии:
1. Я не уверен, где начинаются ваши данные, но это может быть более эффективно
dt[, lapply(.SD, max), Gene]
. Поскольку ваши данные выглядят как символ, использование функцииfunction(x) max(as.numeric(x), na.rm = TRUE)
может помочь. В принципе, попробуйте посмотреть, можете ли вы пропустить свертывание, за которым следует регулярное выражение, путем прямого применения функций к вашим необработанным данным.
Ответ №1:
Вы можете использовать type.convert
и задать его аргумент na.strings
"."
равным . Вы также можете использовать range
функцию, чтобы получить как минимальное, так и максимальное значение за один раз.
Предположим, что ваш data.table
выглядит так
> dt
Gene col1 col2 col3 col4
1: ACE 0.3, 0.4, 0.5, 0.5 . ., ., . 1, 1, 1, 1, 1
2: NOS2 ., . . ., ., ., . 0, 0, 0, 0, 0
3: BRCA1 . ., . 1, 1, 1, 1, 1
4: HER2 . 0.1, ., ., 0.2, 0.1 . 1, 1, 1, 1, 1
Рассмотрим функцию, подобную этой
library(data.table)
library(stringr)
get_range <- function(x) {
x <- type.convert(str_split(x, ",\s ", simplify = TRUE), na.strings = ".")
x <- t(apply(x, 1L, function(i) {
i <- i[!is.na(i)]
if (length(i) < 1L) c(NA_real_, NA_real_) else range(i)
}))
dimnames(x)[[2L]] <- c("min", "max")
x
}
Тогда вы можете просто
dt[, c(Gene = .(Gene), lapply(.SD, get_range)), .SDcols = -"Gene"]
Вывод
Gene col1.min col1.max col2.min col2.max col3.min col3.max col4.min col4.max
1: ACE 0.3 0.5 NA NA NA NA 1 1
2: NOS2 NA NA NA NA NA NA 0 0
3: BRCA1 NA NA NA NA NA NA 1 1
4: HER2 NA NA 0.1 0.2 NA NA 1 1
Обратите внимание, что нет необходимости делать это с помощью Gene
, поскольку функция get_range
уже векторизована.