Search code examples
rplotintervalscontouraxes

Incorrect x and y-axis values of contour2D plot


I would like to see the density of my data so I drew a contour plot using the data pre-processed by cut function, this is a small sample of my data:

> z[1:2,]
           pc2_cut
pc1_cut         (-1.61,-1.45] (-1.45,-1.3] (-1.3,-1.15] (-1.15,-1] (-1,-0.851]
(-1.58,-1.38]             0            1            1          0           0
(-1.38,-1.18]             5            1            4          1           0

I used plot3D library and,

> contour2D(z,border="black",xlab="PC1",ylab="PC2")

This is what I got:

enter image description here

You can see the x-axis and y-axis values are incorrect, not even near the midpoint of the intervals. Does anyone know how to correct this?


Solution

  • The contour2D() function scales the axes between 0 and 1 by default. To get different axes you can omit axes from the original contour2D() call and add them using axis() with at and labels specified. If you are using the factors from cut() you will have to convert them to numeric values before plotting. I have provided an example below where I generate data, plot it, and then adjust the axes labels after converting the factors into numeric values. Without your exact data format I do not know the best way to extract tick mark labels from your data.

    enter image description here

    # library for plot
    library(plot3D)
    
    # setting seed and generating some data
    set.seed(10)
    
    #### storing data in matrix ####
    datamatrix <- matrix(c(rnorm(500,-1,.4),rnorm(500,2,0.2),runif(500,-3,0),runif(500,0,3)),nrow=1000,ncol=2,byrow=F)
    
    # locations of cuts
    xcuts <- seq(min(datamatrix[,1]),max(datamatrix[,1]),length.out = 6)
    ycuts <- seq(min(datamatrix[,2]),max(datamatrix[,2]),length.out = 6)
    
    # calculating values for cutting
    xvals <- cut(datamatrix[,1], xcuts)
    yvals <- cut(datamatrix[,2], ycuts)
    
    # initializing matrix to store count in each bin
    z <- matrix(0,length(levels(yvals)),length(levels(xvals)))
    
    for(i in 1:length(levels(xvals))){
      for(j in 1:length(levels(yvals))){
        z[j,i] <- length(intersect(which(xvals == levels(xvals)[i]),which(yvals == levels(yvals)[j])))
      }
    }
    
    #### finding labels from factors cut ####
    factsx <- levels(xvals) # factsx <- levels_pc2_cut # or something like that
    xlabsFacts <- rep(NA,length(factsx))
    
    for(i in 1:(length(factsx))){
    
      comma_sep <- unlist(gregexpr(pattern =',',factsx[i])) # location of the comma in the factor
    
      #taking section of text and converting to numbers
      xlabsFacts[i] <- as.numeric(substr(factsx[i],2,comma_sep-1))
      xlabsFacts[i+1] <- as.numeric(substr(factsx[i],comma_sep+1,nchar(factsx[i])-1))
    
    }
    
    factsy <- levels(yvals) # factsy <- levels_pc1_cut # or something like that
    ylabsFacts <- rep(NA,length(factsy))
    
    for(i in 1:(length(factsy))){
    
      comma_sep <- unlist(gregexpr(pattern =',',factsy[i])) # location of the comma in the factor
    
      #taking section of text and converting to numbers
      ylabsFacts[i] <- as.numeric(substr(factsy[i],2,comma_sep-1)) 
      ylabsFacts[i+1] <- as.numeric(substr(factsy[i],comma_sep+1,nchar(factsy[i])-1))
    
    }
    
    
    #### formatting plot ####
    # contour plot without axes
    contour2D(z
              ,yaxt='n' # no y axis ticks
              ,xaxt='n' # no x axis ticks
              ,ylab='y values' # y axis label
              ,xlab='x values' # x axis label
    )
    
    # adding x axis with tick marks
    axis(side=1 # bottom
         ,at=seq(0,1,length.out = length(xlabsFacts)) # change 6 to number of tick marks you want
         ,labels=round(xlabsFacts,2) # change to labels for tick marks from your data
    )
    
    # adding x axis with tick marks
    axis(side=2 # bottom
         ,at=seq(0,1,length.out = length(ylabsFacts)) # change 6 to number of tick marks you want
         ,labels=round(ylabsFacts,2) # change to labels for tick marks from your data
    
    )