I have df that looks like following. I would like to build new variable break following rule: if max>60, then break includes (0, min, max, and the numbers /-10 from 0); if max<=60, then break includes (0, min, max, and the numbers /-7 from 0).
I might not describe this clearly. but you can see the expected outcome here:
what should I do? The tricky part is I need to get the seq from 0 /-10, not from min to max, every 10.
df<-structure(list(min = c(-9, -18, 3), max = c(49, 62, 18)), row.names = c(NA,
-3L), class = c("tbl_df", "tbl", "data.frame"))
CodePudding user response:
get_seq <- function(mn,mx,val) {
vals = unique(c(mn, mx, -1*seq(0,abs(mn),by=val),seq(0,mx,val)))
vals[order(vals)]
}
df %>% rowwise() %>%
mutate(break_seq = case_when(
max>60~list(get_seq(min,max,10)),
max<=60~list(get_seq(min,max,7))
)
)
Output:
min max break_seq
<dbl> <dbl> <list>
1 -9 49 <dbl [10]>
2 -18 62 <dbl [10]>
3 3 18 <dbl [5]>
Or, if you want a character string of those numbers, you could do something like this:
get_seq <- function(mn,mx,val) {
vals = unique(c(mn, mx, -1*seq(0,abs(mn),by=val),seq(0,mx,val)))
paste0(vals[order(vals)], collapse=",")
}
df %>% rowwise() %>%
mutate(break_seq = case_when(
max>60~get_seq(min,max,10),
max<=60~get_seq(min,max,7)
)
)
Output:
min max break_seq
<dbl> <dbl> <chr>
1 -9 49 -9,-7,0,7,14,21,28,35,42,49
2 -18 62 -18,-10,0,10,20,30,40,50,60,62
3 3 18 0,3,7,14,18
CodePudding user response:
Here's another function to do this using some modular arithmetic (base R only):
f <- function(mi, ma) {
seq_by <- if (ma > 60) 10 else 7
upper <- if (ma %% seq_by == 0) ma else seq_by * (ma %/% seq_by 1)
lower <- if (mi %% seq_by == 0) mi else seq_by * (mi %/% seq_by)
seq(lower, upper, by = seq_by)
}
mi
and ma
are the min and max values.
df$break <- mapply(f, df[["min"]], df[["max"]])
CodePudding user response:
Another Solution similar to Noah's:
myfun <- function(v) {
max=max(v)
min=min(v)
if (max>60) {
out<- c(seq(from=0,to=max,by=10),seq(from=0,to=min,by=-10))
}else if(max<60){
out<- c(seq(from=0,to=max,by=7),seq(from=0,to=min,by=-7))
}
return(sort(unique(c(out,min,max))))
}
Test:
vec_over60<- c(-32,3,8,4,9,3,33,55,65)
vec_under60<- c(-12,18,44,22,33)
> myfun(vec_over60)
[1] -32 -30 -20 -10 0 10 20 30 40 50 60 65
> myfun(vec_under60)
[1] -12 -7 0 7 14 21 28 35 42 44