Let say i have a data like this
M<- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
The M has 5 columns with the same values which I want to plot it but I don't want to plot them on each other. I want to show them with a space. What I do is like below
plot(x, M[,1], ylim=range(M), ann=FALSE, axes=T,type="l")
Colm <- 2:ncol(M)
lapply(seq_along(Colm),function(i){
lines(x, M[,i], col=Colm[i])
})
Is there any way to make a distance between each line in plot ?
You can add a small change to each y value to shift each line slightly.
set.seed(595)
M <- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
plot(NA, ylim=range(M), xlim=range(x), ann=FALSE, axes=T, type="l")
# Amount by which to shift each y value
eps = seq(-0.1, 0.1, length.out=ncol(M))
lapply(1:ncol(M), function(i){
lines(x, M[,i] + eps[i], col=i)
})
UPDATE: In answer to your comment, I think the following is probably what's happening: In your sample code, x is a matrix, which behaves essentially the same as a vector when the matrix has only one column. Thus, x will return a data vector, so you can just use the object x directly in the lines function. However, if you're importing x as a data frame (for example, using x=read.table("x.txt", header=TRUE), then you need to use lines(x[,1], M[,i] + eps[i], col=i) in your code in order to get the vector of data in the first column of the data frame x.
If you use ggplot you can do this easily using the alpha command as indicated in this post:
Overlapping Lines in ggplot2
and you could also jitter the lines using code from this post..
How to jitter lines in ggplot2
Related
I am trying to draw a barplot in R
I have 2 vectors
x <- c(1,2,3,4)
y <- c(200,400,4000,255)
A <- rbind(x,y) # to make it into a matrix
barplot(A, ylim= c(0,5000))
I want to put at the base of each plot 1,2,3,4 on the x axis.
How can I do that
Thanks
barplot(A, ylim= c(0,5000),names.arg=1:4)
This is how you do it.
My suggestion is that you should check the help manual/doc for each function carefully. R graphic functions usually have lots of arguments for various purposes.
Function "barplot" returns the x-axis value where each bar is centred. We can use these values as a reference to add legend on top of each bar, or any where else (but less straightforward).
To add on the top
x.axis <-barplot(A, ylim= c(0,5000),names.arg=1:4)
text(x.axis, y, adj = c(0.5, 0)) ## you have defined "y"
I have a bunch of XYZ data where X and Y are coordinates and Z is supposed to be the elevation (LiDAR points). I am trying to plot this point cloud with a gradient based on the Z value.
Here is what I have so far:
# Read the CSV file with the LiDAR point cloud (which was conveniently converted to CSV)
myData <- read.csv("./52I212_plot10.las.csv")
# We don't need all attributes, let's keep only X, Y and Z.
myData <- subset(myData, select=c(X,Y,Z))
# We want a normalized version of Z (between 0 and 1)
myData$normalZ <- (myData$Z-min(myData$Z))/(max(myData$Z)-min(myData$Z))
str(myData)
With this I try to create the plot with
library(lattice)
ramp <- colorRampPalette(c("lightblue", "red"))
cloud(myData$Z ~ myData$X + myData$Y, xlab="X", ylab="Y", zlab="Z",pch=20,
col.point=ramp(10)[myData$normalZ*10])
I expected Z values to have one of ten possible colors between lightblue and red.
When I change the plot command to
cloud(myData$Z ~ myData$X + myData$Y, xlab="X", ylab="Y", zlab="Z",pch=20,
col.point=gray(myData$normalZ))
I get something that is much closer to what I need:
I suspect I am doing something wrong on the color ramp, but cannot figure out what.
thanks in advance
Rafael
EDIT
This question: How to match vector values with colours from a colour ramp in R? helped me a lot, but I still don't understand what I did wrong. This code works:
myData$normalZ <- (myData$Z-min(myData$Z))/(max(myData$Z)-min(myData$Z))
ramp <- colorRamp(c("lightblue", "red"))
cols <- ramp(myData$normalZ)
cloud(myData$Z ~ myData$X + myData$Y, xlab="X", ylab="Y", zlab="Z",pch=20,
col.point=rgb(cols,maxColorValue = 256))
Please point what could be changed on the original code to make it work -- I cannot figure out why in the first figure colors appear to be randomish.
thanks
Rafael
Can't confirm without data, but I think 0's are throwing you off. Your normalZ is between 0 and 1, so 10 * normalZ is between 0 and 10. You're passing these non-integers to [ and they get rounded down. (I had to look this up, but from ?"[": "Numeric values [of i] are coerced to integer as by as.integer (and hence truncated towards zero)".
Giving 0 (or anything less than 1) as a subset index messes with your color vector's length and hence how things match up:
ramp(10)[c(0, 0.4, 0.8, 1.2, 1.6)]
# [1] "#ACD8E5" "#ACD8E5"
and then the too-short vector gets recycled. So, your code will probably work with
col.point = ramp(10)[ceiling(myData$normalZ * 10)]
There's a small bug in the mapping of z-values to indices in the color ramp.
library(lattice)
N <- 500
myData <- data.frame(X = runif(N,0,30),
Y = runif(N,0,30),
Z = runif(N,0,300))
myData$normalZ <- (myData$Z-min(myData$Z))/(max(myData$Z)-min(myData$Z))
ramp <- colorRampPalette(c("lightblue", "red"))
cloud(myData$Z ~ myData$X + myData$Y, xlab="X", ylab="Y", zlab="Z",pch=20,
col.point=ramp(10)[myData$normalZ*10])
Here myData$normalZ*10 maps Z-values in (0,1) onto color indices (0,10). (The floating point values get truncated to integers when indexing.) But ramp(10) only returns 10 (not 11) elements, and R vector indexing must start at 1 not 0, so for small Z-values NULL will be returned. Both effects ruin correct color interpolation.
The cloud then looks like this, with incorrect colouring along the Z-axis:
Correct interpolation like this
cloud(myData$Z ~ myData$X + myData$Y, xlab="X", ylab="Y", zlab="Z",pch=20,
col.point=ramp(10)[myData$normalZ*9+1])
returns a result as expected:
Is there any way for me to add some points to a pairs plot?
For example, I can plot the Iris dataset with pairs(iris[1:4]), but I wanted to execute a clustering method (for example, kmeans) over this dataset and plot its resulting centroids on the plot I already had.
It would help too if there's a way to plot the whole data and the centroids together in a single pairs plot in such a way that the centroids can be plotted in a different way. The idea is, I plot pairs(rbind(iris[1:4],centers) (where centers are the three centroids' data) but plotting the three last elements of this matrix in a different way, like changing cex or pch. Is it possible?
You give the solution yourself in the last paragraph of your question. Yes, you can use pch and col in the pairs function.
pairs(rbind(iris[1:4], kmeans(iris[1:4],3)$centers),
pch=rep(c(1,2), c(nrow(iris), 3)),
col=rep(c(1,2), c(nrow(iris), 3)))
Another option is to use panel function:
cl <- kmeans(iris[1:4],3)
idx <- subset(expand.grid(x=1:4,y=1:4),x!=y)
i <- 1
pairs(iris[1:4],bg=cl$cluster,pch=21,
panel=function(x, y,bg, ...) {
points(x, y, pch=21,bg=bg)
points(cl$center[,idx[i,'x']],cl$center[,idx[i,'y']],
cex=4,pch=10,col='blue')
i <<- i +1
})
But I think it is safer and easier to use lattice splom function. The legend is also automatically generated.
cl <- kmeans(iris[1:4],3)
library(lattice)
splom(iris[1:4],groups=cl$cluster,pch=21,
panel=function(x, y,i,j,groups, ...) {
panel.points(x, y, pch=21,col=groups)
panel.points(cl$center[,j],cl$center[,i],
pch=10,col='blue')
},auto.key=TRUE)
This is probably a simple question, but I´m not able to find the solution for this.
I have the following plot (I´m using plot CI since I´m not able to fill the points with plot()).
leg<-c("1","2","3","4","5","6","7","8")
Col.rar1<-c(rgb(1,0,0,0.7), rgb(0,0,1,0.7), rgb(0,1,1,0.7),rgb(0.6,0,0.8,0.7),rgb(1,0.8,0,0.7),rgb(0.4,0.5,0.6,0.7),rgb(0.2,0.3,0.2,0.7),rgb(1,0.3,0,0.7))
library(plotrix)
plotCI(test$size,test$Mean,
pch=c(21), pt.bg=Col.rar1,xlab="",ylab="", ui=test$Mean,li= test$Mean)
legend(4200,400,legend=leg,pch=c(21),pt.bg=Col.rar1, bty="n", cex=1)
I want to creat the same effect but with lines, instead of points (continue line)
Any suggestion?
You have 2 solutions :
Use The lines() function draws lines between (x, y) locations.
Use plot with type = "l" like line
hard to show it without a reproducible example , but you can do for example:
Col.rar1<-c(rgb(1,0,0,0.7), rgb(0,0,1,0.7), rgb(0,1,1,0.7),rgb(0.6,0,0.8,0.7),rgb(1,0.8,0,0.7),rgb(0.4,0.5,0.6,0.7),rgb(0.2,0.3,0.2,0.7),rgb(1,0.3,0,0.7))
x <- seq(0, 5000, length.out=10)
y <- matrix(sort(rnorm(10*length(Col.rar1))), ncol=length(Col.rar1))
plot(x, y[,1], ylim=range(y), ann=FALSE, axes=T,type="l", col=Col.rar1[1])
lapply(seq_along(Col.rar1),function(i){
lines(x, y[,i], col=Col.rar1[i])
points(x, y[,i]) # this is optional
})
When it comes to generating plots where you want lines connected according to some grouping variable, you want to get away from base-R plots and check out lattice and ggplot2. Base-R plots don't have a simple concept of 'groups' in an xy plot.
A simple lattice example:
library( lattice )
dat <- data.frame( x=rep(1:5, times=4), y=rnorm(20), gp=rep(1:4,each=5) )
xyplot( y ~ x, dat, group=gp, type='b' )
You should be able to use something like this if you have a variable in test similar to the color vector you define.
I'm trying to label the points of an ECDF plot with another column from my data field.
Currently I'm using this:
untouched = read.table("results-untouched.tsv", sep="\t")
plot.ecdf(untouched$V4, xlim=c(0.75,1.25), ylim=c(0,1), col='green', verticals=T)
which plots allright, but I'm then unable to add the labels to the points. The labels would be in untouched$V1.
Any idea on how to do this?
To add labels, you can use the text function. For example, we generate some data
x = sort(rnorm(10))
then create the ecdf object (plot.ecdf does this automatically),
m = ecdf(x)
and plot m
plot(m)
To add labels, we use the text function. The x coordinates are the data, the y coordinates are the output from the ecdf function (with an additional 0.03 to avoid over-plotting):
text(x, m(x) + 0.03, LETTERS[1:10])