Jeiran
Jeiran

Reputation: 15

calling an object from a function in R - error object not found

I am trying to create a variable width column chart, each column representing the a non overlapping steps. the width would be the mean of the step and the height is the standard dev of each step. This was my original code:

df <- data.frame (Steps = c( "Step2", "Step3", "Step4", "Step5", "Step6", "Step7"), Variability = c(sd(dataset$PS02_days_creation_to_validation, na.rm = TRUE), sd(dataset$PS03_days_validation_to_sourcing, na.rm = TRUE), sd(dataset$PS04_days_sourcing_to_confirmation, na.rm = TRUE), sd(dataset$PS05_days_confirmation_to_ship_created, na.rm = TRUE),sd(dataset$PS06_days_ship_created_to_shipped, na.rm = TRUE), sd(dataset$PS07_days_shipped_to_reception,na.rm = TRUE) ), width = c(mean(dataset$PS02_days_creation_to_validation, na.rm = TRUE), mean(dataset$PS03_days_validation_to_sourcing, na.rm = TRUE), mean(dataset$PS04_days_sourcing_to_confirmation, na.rm = TRUE), mean(dataset$PS05_days_confirmation_to_ship_created,na.rm = TRUE), mean(dataset$PS06_days_ship_created_to_shipped,na.rm = TRUE), mean(dataset$PS07_days_shipped_to_reception,na.rm = TRUE) ))

df$w <- cumsum(df$width) #cumulative sums to gt the end points of each column.
df$wm <- df$w - df$width #giving the starting point of each column

library(ggplot2)
p  <- ggplot(df, aes(ymin = 0))
p1 <- p + geom_rect(aes(xmin = wm, xmax = w, ymax = Variability, fill = Steps))
p1

This code works fine when all the steps are positive. However when the width of the first step is negative, then my columns would overlap.
i.e. 4 steps with the following width =(25,50,75,100), using the above code creates: end point w= (25,75,150,250) starting point wm= (0,25,75,150). Great!

Now if the the first step's width change to (-25,50,75,100) then the code produces w:(-25,25,100,200) and wm:(0,-25,25,100) which means that the steps are overlapping!! Instead i would like to amend the code to produce: w=(-25,50,125,225) and wm:(0,0,50,125)

An R guru kindly suggested using this function:

widths_to_starts_ends <- function(widths){
  
  widths <- widths[widths != 0]
  pos_widths <- widths[widths > 0]
  neg_widths <- widths[widths < 0]
  
  pos_ends <- cumsum(pos_widths)
  pos_starts <- cumsum(pos_widths) - pos_widths
  
  neg_widths <- abs(neg_widths)
  neg_starts <- cumsum(neg_widths)
  neg_ends <- cumsum(neg_widths) - neg_widths
  
  neg_starts <- (-1)*neg_starts
  neg_ends <- (-1)*neg_ends
  
  return( list(s = c(neg_ends, pos_starts), e = c(neg_starts, pos_ends)) )
  
}

widths_to_starts_ends(c(-25,50,75,100))

which results in

$s 
[1] 0   0  50 125

$e
[1] -25  50 125 225 

I would like to embed this function into my original code (to replace the w and wm lines with e and s) and make a graph but i am not sure how to call the objects E and S. this is what im doing:

library(ggplot2)
p  <- ggplot(df, aes(ymin = 0))

p1 <- p + geom_rect(aes(xmin = s, xmax = e, ymax = Variability, fill = Steps))
p1

But it says object S is not found. Could you help me please?

Upvotes: 1

Views: 1158

Answers (2)

marcguery
marcguery

Reputation: 586

If I understand it correctly, you want to make a continuous series of intervals that are shifted by the first value of your list if it is negative.

Here is something more compact than what you have already to produce such intervals and store them in your dataframe:

df$e <- cumsum(abs(df$width)) + min(0, df$width[1])
df$s <- c(min(0, df$width[1]), df$e[-length(df$e)])
df$s #starting points
#[1] -25   0  50 125
df$e #ending points
#[1]   0  50 125 225

Then, the corresponding plot would be obtained with:

p  <- ggplot(df, aes(ymin = 0))
p1 <- p + geom_rect(aes(xmin = s, xmax = e, ymax = Variability, fill = Steps))
p1

enter image description here

Data that I used:

set.seed(123456789)
df <- data.frame (Steps = c( "Step2", 
                             "Step3", 
                             "Step4", 
                             "Step5"), 
                  Variability = c(sd(1:500/sample(1:10, 1)), 
                                  sd(1:500/sample(1:10, 1)), 
                                  sd(1:500/sample(1:10, 1)), 
                                  sd(1:500/sample(1:10, 1))), 
                  width = c(-25,50,75,100))

Upvotes: 0

Elle
Elle

Reputation: 1008

s and e appear to be elements of a list, not standalone objects, which I imagine is why they can’t be found. In your function you could instead return a dataframe df containing s and e columns and then make your ggplot call

ggplot(df, aes(xmin = s, xmax = e...)) + geom_rect()

Upvotes: 1

Related Questions