#r #variables #dplyr
Вопрос:
Работа над сценарием для анализа результатов секвенирования SARS-CoV-2 для импорта в нашу лабораторную информационную систему. Необходимо проверить, включены ли позиции нуклеотидов для ключевых мутаций в данные консенсусной последовательности. Данные о позициях отсутствующих нуклеотидных последовательностей включаются в виде строковой переменной, разделенной запятыми, где диапазоны разделены «-«. Я подумал, что я напишу цикл for, который проверяет каждую позицию ключевого нуклеотида на наличие определенной мутации в соответствии с отсутствующими данными, определенными в строковой переменной. Пока что:
library(tidyverse)
Создание тестовых данных
subs <- as.character(c("A", "B", "C", "D"))
subs_pos <- as.numeric(c("1", "30","22700", "13500"))
df <- data.frame("id" = letters[1:5],
"missing" = as.character(c("1-13030,13364-13626,13962-15504,15862-26543,26891-29904",
"1-29,21717,29727-29777,29837-29904",
"19276-19571,22627-22822,29837-29904",
"29837-29904",
"1-10,20-30"
)))
фрейм данных:
id missing
1 a 1-13030,13364-13626,13962-15504,15862-26543,26891-29904
2 b 1-29,21717,29727-29777,29837-29904
3 c 19276-19571,22627-22822,29837-29904
4 d 29837-29904
5 e 1-10,20-30
для петли
for(i in seq_along(subs)) {
new_var = as.character(subs[i])
print(new_var)
nn = as.numeric(subs_pos[i])
print(nn)
df <- df %>%
mutate(!!new_var := ifelse(!!nn %in%
as.numeric(
source(textConnection(paste("c(", gsub("\-", ":", missing),")")))$value), "I", "N"))
}
Печать на экране и результирующий кадр данных:
>[1] "A"
>[1] 1
>[1] "B"
>[1] 30
>[1] "C"
>[1] 22700
>[1] "D"
>[1] 13500
> df
> id missing A B C D
>1 a 1-13030,13364-13626,13962-15504,15862-26543,26891-29904 I I N N
>2 b 1-29,21717,29727-29777,29837-29904 I I N N
>3 c 19276-19571,22627-22822,29837-29904 I I N N
>4 d 29837-29904 I I N N
>5 e 1-10,20-30 I I N N
Ожидаемый фрейм данных:
> id missing A B C D
> 1 a 1-13030,13364-13626,13962-15504,15862-26543,26891-29904 I I N I
> 2 b 1-29,21717,29727-29777,29837-29904 I N N N
> 3 c 19276-19571,22627-22822,29837-29904 N N I N
> 4 d 29837-29904 N N N N
> 5 e 1-10,20-30 I I N N
Если запустить для одного экземпляра, тест сработает
> 13500 %in% as.numeric(source(textConnection(paste("c(", gsub("\-", ":", df$missing[1]),")")))$value)
[1] TRUE
Мне кажется, что результаты моего кода в результатах последней выполняемой оценки применяются ко всем строкам во фрейме данных. Я подтвердил это, изменив данные теста.
Ответ №1:
Мы могли бы разделить «отсутствующие», ,
чтобы расширить строки, создать новые столбцы «начало», «остановка», разделив разделитель -
(«df1»)
library(dplyr)
library(tidyr)
df1 <- df %>%
separate_rows(missing, sep = ",") %>%
separate(missing, into = c('start', 'stop'), convert = TRUE)
Теперь мы используем метод OP для создания новых столбцов с вектором ‘subs’
for(i in seq_along(subs)) {
df1 <- df1 %>%
mutate(!! subs[i] := case_when(!is.na(stop) amp;
start <= subs_pos[i] amp; stop >= subs_pos[i] ~ 'I', TRUE ~'N'))
}
Сгруппированные по «id», summarise
столбцы «subs» для возврата «I», если есть какие-либо » I » или «N», объедините исходные данные и select
столбцы в нужном нам порядке
df1 %>%
group_by(id) %>%
summarise(across(c(A:D), ~ case_when('I' %in% . ~ 'I',
TRUE ~ 'N'))) %>%
right_join(df) %>%
select(names(df), everything())
-выход
# A tibble: 5 x 6
# id missing A B C D
# <chr> <chr> <chr> <chr> <chr> <chr>
#1 a 1-13030,13364-13626,13962-15504,15862-26543,26891-29904 I I I I
#2 b 1-29,21717,29727-29777,29837-29904 I N N N
#3 c 19276-19571,22627-22822,29837-29904 N N I N
#4 d 29837-29904 N N N N
#5 e 1-10,20-30 I I N N
Ответ №2:
Другое решение, предложенное коллегой:
for(i in 1:nrow(df)){
ranges <- as.numeric(source(textConnection(paste("c(", gsub("\-", ":", df$missing[i]),")")))$value)
for(j in 1:length(subs)){
if(subs_pos[j] %in% ranges) {
df[i,][subs[j]] <- "I"
}
}
}
}