Search code examples
rggplot2line-plot

Adding layer of interpolated values to ggplot chart in R


I have created the following dataframe in R to generate a plot using ggplot

 library(data.table)
 library(ggplot2)
 library(plotly)

     df <- data.frame("X_Frequency" = c(5, 10, 55, 180, 300, 360, 1000, 2000) 
       , "X_Axis" = c(0.009185742, 0.207822221, 0.067542222, 0.002597778, 
       0.002597778, 0.001454756, 0.001454756 , 0.001454756))

Next I have generated a plot using ggplot

        B <- ggplot(data = df, 
        mapping = aes(x = X_Frequency, y = X_Axis)) +  
        geom_line() + labs(x = "Frequency(Hz)", y="Axis")

        B <- ggplotly(B, dynamicTicks = TRUE)###Hovering enabled
        B <- layout(B, yaxis = list(type = "log"))##X Y log scales enabled
        B <- layout(B, xaxis = list(type = "log"))

        B

I have created the following dataframe df241 with interpolated values between various observations in df1. First we create the slopes

   df$X_Slope2 <- 0### Initiate slope column
   for(i in 2:nrow(df)){
   df$X_Slope2[i] = (df$X_Axis[i] - df$X_Axis[i-1]) / 
   (df$X_Frequency[i] - df$X_Frequency[i - 1])
                                     }

Next we assign the respective slopes to all values

     df_new <- bind_cols(df %>%
     select(X_Frequency, X_Axis, X_Slope2) %>%
     complete(., expand(., X_Frequency = 5:2000))

Now we calculate the interpolated values of X-Frequency, X_Axis from the df_new using slopes

       for(i in 1: nrow(df241)){
       if(is.na(df241$X_Axis[i]) == T){
       df241$X_Axis[i] = df241$X_Slope2[i] * 
       (df241$X_Frequency[i] - df241$X_Frequency[i-1]) +
       df241$X_Axis[i-1]  } else {
       df241$X_Axis[i] = df241$X_Axis[i]}} 

I want to place these interpolated values from df241 on the original chart B generated above. How can this be accomplished. I request someone to help me.

Note: I have tried generating a new plot based df_new dataframe. but the chart appears very different from the original chart -B.


Solution

  • It might be simpler to use the approx function for your interpolation. I believe this gets a similar result as your interpolation steps.

    df_interp <- approx(df$X_Frequency, df$X_Axis, xout = 5:2000) %>%
      as_tibble() %>%
      rename(X_Frequency = x, X_Axis = y)
    

    A linear interpolation may look unexpected on a log-log scale. I was unable to run your code as provided (is df241 created somewhere?), so I'm not sure if this is what you encountered when you said the chart with the interpolated values appears very different.

    B <- ggplot(data = df, 
                mapping = aes(x = X_Frequency, y = X_Axis)) +  
      geom_line() + 
      geom_point(data = df_interp, size = 0.1, color = "blue") +
      labs(x = "Frequency(Hz)", y="Axis")
    B <- ggplotly(B, dynamicTicks = TRUE)###Hovering enabled
    B <- layout(B, yaxis = list(type = "log"))##X Y log scales enabled
    B <- layout(B, xaxis = list(type = "log"))
    B
    

    enter image description here

    Edit: interpolation on log scale

    Alternatively, you could interpolate using log-transformed inputs, and then use exp to convert back onto the original scale:

    df_interp <- approx(log(df$X_Frequency), log(df$X_Axis), xout = log(5:2000)) %>%
      as_tibble() %>%
      mutate(X_Frequency = exp(x),
             X_Axis = exp(y))
    

    Which would result in this:

    enter image description here