# How to partially compress domain of a scatter plot?

I am not sure where should I place this question. It is a more general question. My question is:

I have scatter plot with 1 million points. I am using R to plot my data. When I plot my data points, approximately 10,000 point are plotted at the beginning of 75% of the domain and remaining are in 25% towards the end. Both parts of my graph capture some important feature and can't be neglected.

I am willing to plot my data such that 75% of the original domain appears in 20% of the domain (compress) and 25% of the domain (at the end) stretches to remaining 80% of the domain.

Can you please suggest any transformation?

Domain (X-Axis) is in between 2.5 to 3.3 and and range (Y-axis) is 0 to 5E4. For every value of x-axis, there are 300 points.

Here is code that will produce data similar to one. I want to compress part of the graph from 2.5 to 3.22 and for X>3.2 should stretch (say 80% of the plot).

myList <- list()
for (i in seq(2.5, 3.1, 0.001)){
lst <- list()
lst <- cbind(lst,rep(i,300))
y <- floor(runif(2, 2E4,2.2E4))
v <- rep(0,300)
for (j in 1:length(lst))
v[j]=y[floor(runif(1,1,2))]
lst <- cbind(lst,v)
myList[[length(myList)+1]] <- lst

}

for (i in seq(3.101, 3.22, 0.001)){
lst <- list()
lst <- cbind(lst,rep(i,300))
y   <- floor(runif(4, 1.5E4,2.8E4))
v   <- rep(0,300)
for (j in 1:length(lst))
v[j]=y[floor(runif(1,1,4))]
lst <- cbind(lst,v)
myList[[length(myList)+1]] <- lst
}

for (i in seq(3.221, 3.3, 0.001)){
lst <- list()
lst <- cbind(lst,rep(i,300))
y <- floor(runif(250, 0,5E4))
v <- rep(0,300)
for (j in 1:length(lst))
v[j]=y[floor(runif(1,1,250))]
lst <- cbind(lst,v)
myList[[length(myList)+1]] <- lst
}

plot(0,0,xlim=c(2.5, 3.29),ylim=c(0,5E4),xlab="",ylab="")

for (i in 1:length(myList)){
points(myList[[i]][,1],myList[[i]][,2],col='black',pch=20,cex=0.05)
}


• "I have scatter plot with 1 million points." You should create a hexbin plot instead. Anyway, you should provide a mock-up of your data. No need for a million points, a few are sufficient to indicate the properties (range, distribution, etc.) of your data. – Roland Dec 19 '18 at 13:45
• How about three graphs? One full the full domain, one for the first 75% or the range and the third for the last 25%. – G5W Dec 19 '18 at 14:16
• Roland, It is difficult to produce a mock data. – bell Dec 19 '18 at 14:23
• At "I am willing" it sounds like you are stating you want the scatterplot to make an inaccurate portrayal of your data. Why? If we understood the motivation, we might be able to understand the question and provide useful answers. Many readers would otherwise be uneasy providing advice about creating a false representation of data. – whuber Dec 19 '18 at 15:43
• I have just posted R code with that will generate data similar to mine. Plot is also added. – bell Dec 19 '18 at 17:30

In a comment was suggested a better idea: to try a hexbin plot. I will show here how that can be done in R, using ggplot2. But first some data cleanup. The myList list object in your code have a strange structure, using R becomes easier after some cleanup:

myData  <-  do.call(rbind,  myList)
myData  <-  data.frame(myData)
myData  <-  data.frame(x=unlist(myData[, 1]), y=unlist(myData[, 2]))
# remaking above plot:
plot(myData,  pch=20, cex=0.05, xlab="", ylab="") # Not shown here


Then:

library(ggplot2)
ggplot(myData, aes(x, y))+geom_hex(alpha=0.5)+scale_fill_continuous(low="blue", high="red")


• Thanks for showing this solution and data cleanup. But I want to stretch the region for x>3.2 and compress for the region x<3.2 on the same graph. – bell Dec 20 '18 at 11:45

Building on kjetil b halvorsen's ideas and code (+1), I suggest simply raising the X-axis values to a power that suits your needs.

#Using kjetil b halvorsen's code
myData  <-  do.call(rbind,  myList)
myData  <-  data.frame(myData)
myData  <-  data.frame(x=unlist(myData[, 1]), y=unlist(myData[, 2]))

#Generating hexbin plot. This differs only in raising the X-values to the 10th power.
#The X-axis ticks can be recalculated on the original scale to make it easier to interpret,
#but I have not done that here
library(ggplot2)
ggplot(myData, aes(x^10, y))+geom_hex(alpha=0.5)+scale_fill_continuous(low="blue", high="red")