Home > other >  how to get a seq of 5 from 0 instead from min to max
how to get a seq of 5 from 0 instead from min to max

Time:03-09

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:

enter image description 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
  •  Tags:  
  • r
  • Related