#r
Вопрос:
У меня есть набор данных.
test
Intervar
1 Uncertain significance PVS1=0 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
2 Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
3 Pathogenic PVS1=1 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
4 Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
5 Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
6 Likely benign PVS1=0 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 1, 0, 0, 1, 0]
7 Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
8 Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]
Каждая строка следует одному и тому же шаблону:
Pathogenic/Likely pathogenic/Uncertain significance/Likely benign/Benign PVS1=0 PS=[0,0,0,0,0] PM=[0,0,0,0,0,0,0] PP=[0,0,0,0,0,0] BA1=0 BS=[0,0,0,0,0] BP=[0,0,0,0,0,0,0,0]
Я хочу разделить его на несколько столбцов и назвать столбец на основе символа перед знаком равенства.
PVS1 PS1 PS2 PS3 PS4 PS5 PM1 PM2 PM3 PM4 PM5 PM6 PM7 PP1 PP2 PP3 PP4 PP5 PP6 ... BP1 BP2 BP3 BP4 BP5 BP6 BP7 BP8
1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0
2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0
3 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0
4 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0
5 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 1 0 0 1 0
7 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0
8 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0
данные
structure(list(Intervar = c("Uncertain significance PVS1=0 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]",
"Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]",
"Pathogenic PVS1=1 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]",
"Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]",
"Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]",
"Likely benign PVS1=0 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 1, 0, 0, 1, 0]",
"Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]",
"Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]"
)), class = "data.frame", row.names = c(NA, -8L))
Я попробовал следующий код, чтобы разделить его и суммировать число в той же скобке, что и в предыдущем ответе на другой предложенный вопрос.
test$Intervar %>%
gsub(" (\w =)", "n\1", .) %>%
paste0("nDescription=", .) %>%
gsubfn("\[(.*?)\]", ~ sum(scan(text = txt, sep = ",", quiet = TRUE)), .) %>%
gsub("=", ": ", .) %>%
textConnection %>%
read.dcf %>%
as.data.frame %>%
type.convert
Результат был таким
Description PVS1 PS PM PP BA1 BS BP
1 Uncertain significance 0 1 1 0 0 0 0
2 Pathogenic 1 0 1 1 0 0 0
3 Pathogenic 1 1 1 1 0 0 0
4 Pathogenic 1 0 1 1 0 0 0
5 Pathogenic 1 0 1 1 0 0 0
6 Likely benign 0 0 1 0 0 0 2
7 Pathogenic 1 0 1 1 0 0 0
8 Pathogenic 1 0 1 1 0 0 0
Но на этот раз я хочу, чтобы все числа в скобке sampe были разделены.
Комментарии:
1. 1) Пожалуйста, предоставьте воспроизводимый набор данных 2) Пожалуйста, предоставьте то, что вы уже пробовали.
2. @RobinGertenbach Спасибо за предложения. Я отредактировал вопрос.
Ответ №1:
Извлеките цифры, которые начинаются с границы слова, преобразуя их в числовые, давая матрицу m
.
Оставшаяся часть кода вычисляет имена столбцов.
- Сначала определите регулярное выражение, соответствующее слову, за которым следует знак равенства, фиксирующий это слово. Извлеките их в
vars
. То естьvars
равныc("PVS1", "PS", "PM", "PP", "BA1", "BS", "BP")
. - Затем разделите первую строку тем же регулярным выражением. Это создает список длины 1, содержащий вектор символов, поэтому извлеките вектор символов с помощью [[1]] и удалите первый элемент [-1], который нам не нужен. Теперь подсчитайте количество оставшихся полей, разделенных запятыми. Это даст числовой вектор
lens
, с длинами каждого из векторов 0/1.lens
являетсяc(1, 5, 7, 6, 1, 5, 8)
. - Используя
vars
иlens
мы можем вычислить имена столбцов.
В результате получается числовая матрица m
. (Необязательно используйте data.frame(m)
, если вы предпочитаете фрейм данных, хотя, учитывая, что он полностью числовой, матрица на самом деле более подходящая.)
library(gsubfn)
m <- do.call("rbind", strapply(dat[, 1], "\b(\d)", as.numeric, perl = TRUE))
pat <- "(\w )="
vars <- strapplyc(dat[1,1], pat, simplify = unlist)
lens <- count.fields(textConnection(strsplit(dat[1,1], pat)[[1]][-1]), ",")
colnames(m) <- unlist(Map(function(v, n) paste0(v, 1:n), vars, lens))
подача (продолжение после вывода):
> m
PVS11 PS1 PS2 PS3 PS4 PS5 PM1 PM2 PM3 PM4 PM5 PM6 PM7 PP1 PP2 PP3 PP4 PP5
[1,] 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
[2,] 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
[3,] 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
[4,] 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
[5,] 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
[6,] 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
[7,] 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
[8,] 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
PP6 BA11 BS1 BS2 BS3 BS4 BS5 BP1 BP2 BP3 BP4 BP5 BP6 BP7 BP8
[1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 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 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0
[7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
>
Поочередно замените последние 4 строки кода, которые вычисляют и задают имена столбцов, на
vars <- c("PVS1", "PS", "PM", "PP", "BA1", "BS", "BP")
lens <- c(1, 5, 7, 6, 1, 5, 8)
colnames(m) <- unlist(Map(function(v, n) paste0(v, 1:n), vars, lens))
или с
colnames(m) <-
c("PVS11", "PS1", "PS2", "PS3", "PS4", "PS5", "PM1", "PM2", "PM3",
"PM4", "PM5", "PM6", "PM7", "PP1", "PP2", "PP3", "PP4", "PP5",
"PP6", "BA11", "BS1", "BS2", "BS3", "BS4", "BS5", "BP1", "BP2",
"BP3", "BP4", "BP5", "BP6", "BP7", "BP8")
Ответ №2:
Возможно, вы могли бы попробовать что-то подобное с dplyr, tidyr и stringr :
# split on spaces excepted those in bracketed lists
df1 <- x %>% mutate(id=row_number(),
a=intervar %>% str_replace_all("(?<=,) ","") %>% str_split(" ")) %>%
unnest(a) %>%
select(id,a)
# Variable names = bracketed list
df2 <- df1 %>%
filter(str_detect(a,"=\[")) %>%
separate(a,into=c("v","l"),sep='=') %>%
mutate(l=l %>% str_replace_all("[\[\]]","") %>% str_split(",")) %>%
unnest(l) %>%
group_by(id,v) %>%
mutate(v = paste0(v,row_number()))
# Variable names without bracketed list
df3 <- df1 %>% filter(str_detect(a,"=(?!\[)")) %>%
separate(a,into=c("v","l"),sep='=')
# Description
df4 <- x %>% mutate(id=row_number(),decription=str_extract(intervar,"^.*(?= PVS)"))
# Final result
inner_join(df4,bind_rows(df2,df3) %>% arrange(id,v) %>% spread(v,l) ,by="id")
Ответ №3:
Не уверен, насколько это эффективно
library(dplyr)
library(tidyr)
library(data.table) #for 'rleid()'
df %>%
mutate(Intervar = trimws(gsub('Pathogenic|Likely pathogenic|Uncertain significance|Likely benign|Benign', '', Intervar)),
Intervar = gsub(', ', ',', Intervar) ) %>%
separate_rows(Intervar, sep = ' ') %>%
separate(Intervar, into = c('nms', 'vals'), sep = '=') %>%
mutate(vals = trimws(gsub('\D ', ' ', vals))) %>%
separate_rows(vals, sep = ' ') %>%
mutate(new = rleid(nms)) %>%
group_by(new) %>%
mutate(nms = make.unique(nms)) %>%
ungroup() %>%
select(-new) %>%
pivot_wider(names_from = nms, values_from = vals)%>%
unnest()
PVS1 PS PS.1 PS.2 PS.3 PS.4 PM PM.1 PM.2 PM.3 PM.4 PM.5 PM.6 PP PP.1 PP.2 PP.3 PP.4 PP.5 BA1 BS BS.1 BS.2 BS.3 BS.4 BP BP.1 BP.2 BP.3 BP.4 BP.5 BP.6 BP.7
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0
7 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0