简体   繁体   中英

Plotting huge number of lines in R

I have written a code to plot nearly 100000 lines in a graph with different colors depending on different conditions. The code is as following.

for(i in c(160000:260000)){
  if(data[i,]$Char1 == 'A' & data[i,]$Char2 == 'S'){
    if(data[i,]$Q1 < data[i,]$Q2){
      lines(c(i,i),c(data[i,]$P + 2,data[i,]$P + 22),col="green")
    }else{
      lines(c(i,i),c(data[i,]$P - 2,data[i,]$P - 22),col="green")
    }
  }
  if(data[i,]$Char1 == "B" & data[i,]$Char2 == 'S'){
    lines(c(i,i),c(data[i,]$P + 2,data[i,]$P + 22),col='blue')
  }
}

I have Plotted a normal graph before that. Which is

plot(data$P,type="l")

I ran the code and for more than 2-3 hours it kept on running till the point I stopped it. Is there any way to do this task easily and with less amount of time?

You may be able to save some computation time by not actually displaying the plot. Running

library(scales)
n <- 100000
m <- 20

system.time({
  plot(0, 0, type = 'n', xlim = c(0, 10), ylim = c(0, 10), xlab = '', ylab = '')
  for (i in 1:n) lines(sort(runif(m, max = 10)), sort(runif(m, max = 10)), 
                       col = ifelse(i %% 10 == 0, 'red', alpha('lightblue', 0.1)), 
                       lwd = 0.2)
})

vs.

system.time({
  png('plot.png')
  plot(0, 0, type = 'n', xlim = c(0, 10), ylim = c(0, 10), xlab = '', ylab = '')
  for (i in 1:n) lines(sort(runif(m, max = 10)), sort(runif(m, max = 10)), 
                       col = ifelse(i %% 10 == 0, 'red', alpha('lightblue', 0.1)), 
                       lwd = 0.2)
  dev.off()
})

gives

  user  system elapsed 
44.415   0.704  45.435 

vs.

  user  system elapsed 
23.115   0.294  23.585 

on my machine. 结果

Update

Using CathG's answer brings down the computation time drastically when plotting lines:

n <- 100000
data <- data.frame(x0 = runif(n), y0 = runif(n), x1 = runif(n), 
                   y1 = runif(n), col = 1:10)

system.time({
  png('plot.png', 640, 640)
  plot(0, 0, type = 'n', xlab = '', ylab = '', xlim = c(0, 1), ylim = c(0, 1))
  for (i in 1:n) lines(data[i, c(1, 3)], data[i, c(2, 4)], col = data$col, 
                       lwd = 0.1)
  dev.off()
})

system.time({
  png('plot.png', 640, 640)
  plot(0, 0, type = 'n', xlab = '', ylab = '', xlim = c(0, 1), ylim = c(0, 1))
  segments(data$x0, data$y0, data$x1, data$y1, col = data$col, lwd = 0.1)
  dev.off()
})

gives

   user  system elapsed 
119.682   0.822 121.525 

vs.

 user  system elapsed 
2.267   0.020   2.303 

I think you should compute the different x and y (and color ) first and then plot them all in one call with segments and I also think you should directly plot them using png for example and not in the window device:

data2 <- data[160000:260000, ]

data2$x0 <- data2$x1 <- 160000:260000

cond1 <- (data2$Char1=="A") & (data2$Char2 == "S") & (data2$Q1 < data2$Q2)
cond2 <- (data2$Char1=="A") & (data2$Char2 == "S") & (data2$Q1 >= data2$Q2)
cond3 <- (data2$Char1=="B") & (data2$Char2 == "S")

data2$y0[cond1] <- data2$P[cond1] + 2
data2$y0[cond2] <- data2$P[cond2] - 2
data2$y0[cond3] <- data2$P[cond3] + 2

data2$y1[cond1] <- data2$P[cond1] + 22
data2$y1[cond2] <- data2$P[cond2] - 22
data2$y1[cond3] <- data2$P[cond3] + 22

data2$color[cond1] <- "green"
data2$color[cond2] <- "green"
data2$color[cond3] <- "blue"

png("nameofyourfile.png")
plot(data$P,type="l")
segments(data2$x0, data2$y0, data2$x1, data2$y1, col=data2$color)
dev.off()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM