I have a data frame where one column contains a range (or ranges) of numbers. I would like to turn this into a list of numbers based of the given range.
Example input:
"35-40"
or
"35-43, 45-47"
This should yield:
[1] 35 36 37 38 39 40
and
[1] 35 36 37 38 39 40 41 42 43 45 46 47
We can do a split and with Map
, get the numbers
do.call(Map, c(`:`, lapply(strsplit(df1$v1, '-'), as.numeric)))
#[[1]]
# [1] 35 36 37 38 39 40 41 42 43 44 45
#[[2]]
#[1] 43 44 45 46 47
If we need to find the sequence within the string
lapply(strsplit(df1$v1, "-"), function(x) Reduce(`:`, as.numeric(x)))
#[1]]
#[1] 35 36 37 38 39 40 41 42 43
#[[2]]
#[1] 45 46 47
Update
If we have multiple elements in a string
df1 <- structure(list(v1 = c("35-43", "45-47", "30-42, 25-27")),
.Names = "v1", row.names = c(NA,
-3L), class = "data.frame")
lapply(strsplit(df1$v1, ", "), function(x) do.call(c,
lapply(strsplit(x, "-"), function(y) Reduce(`:`, as.numeric(y)))))
data
df1 <- structure(list(v1 = c("35-43", "45-47")), .Names = "v1", row.names = c(NA,
-2L), class = "data.frame")
You can use eval(parse(...))
as follows,
eval(parse(text = sub('-', ':', '35-40')))
#[1] 35 36 37 38 39 40
or
unlist(lapply(sub('-', ':', c('35-40', '45-47')), function(i) eval(parse(text = i))))
#[1] 35 36 37 38 39 40 45 46 47
EDIT
Based on your latest edit, then,
unlist(lapply(strsplit(x, ', '), function(i) {
ind <- sub('-', ':', i); unlist(lapply(ind, function(j) eval(parse(text = j))))
}))
#[1] 35 36 37 38 39 40 41 42 43 45 46 47
we use substr to extract parts of string to get beginning and end of numeric list. we use as.numeric to convert strings extracted to numbers. we use the colon to create the list of numbers . it will also work for multiple parts of list
> input
[1] "35-40"
> instart=substr(input,1,2)
> instart
[1] "35"
> inend=substr(input,4,5)
> inend
[1] "40"
> newlist=as.numeric(instart):as.numeric(inend)
> newlist
[1] 35 36 37 38 39 40