Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quickly interpolate missing values in R plot

I would like an efficient way to plot data frames with missing values as a line plot in R, by the following rationale;

  • NAs in first and last values are omitted completely (no line/dots)
  • NAs within actual values are replaced with intermediate values for line plotting (no dots appearing)

This is an example of my data frame (edited)

df <- data.frame("time" = c(1,2,3,4,5),
             "case1" = c(NA,2,3,4,NA),
             "case2" = c(5,4,3,2,NA),
             "case3" = c(4,NA,NA,NA,2))

And this is how it's working for the first case only

library(pracma)
df$case1.i <- with(df, interp1(time, case1, time, 'linear'))
library(ggplot2)
ggplot(df, aes(time)) + geom_point(aes(case1 = case1)) + geom_line(aes(case1 = case1.i))

I'm trying to work out something to make it work for the approximately 200 columns that I have in my actual data frame. So far this code doesn't seem to be working

for (i in colnames(df)){
  argument <- paste("df$case",i,".i <- with(df, interp1(time, case",i,", time, 'linear'))")
  eval(parse(text=argument))
}
like image 296
civy Avatar asked Jul 27 '26 20:07

civy


1 Answers

Read the data into a new zoo object z, apply na.approx to it to fill in the NA values within the body of the data and then plot using ggplot2. If separate panels are wanted omit facet = NULL. Note that fortify.zoo with melt = TRUE converts the data to long form with Index, Series and Value columns and that is used in geom_point. Omit the geom_point(...) part if you just want lines. See image at end of this answer. The approach shown here is relatively compact and avoids pasting together and then evaluating code.

library(ggplot2)
library(zoo)

z <- read.zoo(df)
autoplot(na.approx(z), facet = NULL) + 
  geom_point(aes(Index, Value, group = Series), fortify(z, melt = TRUE))

or if you want a separate plot for each column try this instead:

pdf("civy.pdf")

for(i in 1:ncol(z)) {
  p <- autoplot(na.approx(z[, i])) + 
    ylab(names(z)[i]) +
    geom_point(aes(Index, Value), fortify(z[, i], melt = TRUE))
  plot(p)
}

dev.off()

screenshot

like image 92
G. Grothendieck Avatar answered Jul 29 '26 11:07

G. Grothendieck



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!