У меня есть фрейм данных со столбцом, содержащим диапазоны значений, а также отдельные значения, как показано ниже:
x <- c("a","b")
y <- c("1:3,7","9")
dat <- data.frame("char"=x,"range"=y)
> dat
char range
1 a 1:3,7
2 b 9
Что мне нужно сделать, так это преобразовать столбец range
так, чтобы отображались все значения, содержащиеся в диапазонах:
> dat2
char range
1 a 1,2,3,7
2 b 9
Я добился прогресса благодаря решению, представленному в очень похожем вопросе:
v1 <- c("1:3")
unlist(lapply(v1, function(x) eval(parse(text=x))))
[1] 1 2 3 9
Но это только заводит меня, потому что, конечно, если я передам вектор, который также имеет одиночные значения, как мой исходный столбец range
, он выдаст ошибку:
v1 <- c("1:3,7","9")
unlist(lapply(v1, function(x) eval(parse(text=x))))
Error in parse(text = x) : <text>:1:4: unexpected ','
1: 1:3,
^
Кроме того, я не могу автоматически применить это решение к столбцу фрейма данных, поскольку оно возвращает отдельные числовые значения, а мне нужна строка символов. Любая помощь приветствуется.
РЕДАКТИРОВАТЬ
Спасибо всем за очень полезные комментарии!
Следующая модификация дает вам то, что вы хотите...
v1 <- c("1:3,7","9")
unlist(lapply(v1, function(x) paste(eval(parse(text=paste0("c(",x,")"))),
collapse = ",")))
[1] "1,2,3,7" "9"
Используйте gsubfn
, чтобы сопоставить цифры, двоеточие и цифры, а затем преобразуйте их, используя функцию, указанную в обозначении формулы, заменяя совпавшую строку. Обратите внимание, что seq
может принимать строковые аргументы и интерпретировать их как числовые.
library(dplyr)
library(gsubfn)
dat %>%
mutate(range=gsubfn("(\\d+):(\\d+)", ~paste(seq(x,y), collapse = ","), range))
предоставление
char range
1 a 1,2,3,7
2 b 9
Возможно, попробуйте этот метод, который использует sapply
и не полагается на eval
:
sapply(strsplit(v1, ","), function(x) paste(unlist(sapply(strsplit(x, ":"),
function(y) if (length(y)==2) seq(as.integer(y[1]),as.integer(y[2]))
else as.integer(y))), collapse = ","))
Очень похоже на ответ @Andrew Gustar:
> sapply(v1, \(x) toString(eval(parse(text=paste0("c(",x,")")))))
1:3,7 9
"1, 2, 3, 7" "9"