I'm working with circular data and I wanted to reproduce this kind of plot using ggplot2:
library(circular)
data1 <- rvonmises(1000, circular(0), 10, control.circular=list(units="radians")) ## sample
quantile.circular(data1,c(0.05,.95)) ## for interval
data2 <- mean(data1)
dens <- density(data1, bw=27)
p<-plot(dens, points.plot=TRUE, xlim=c(-1,2.1),ylim=c(-1.0,1.2),
main="Circular Density", ylab="", xlab="")
points(circular(0), plot.info=p, col="blue",type="o")
arrows.circular(c(5.7683795,0.5151433 )) ## confidence interval
arrows.circular(data2, lwd=3) ## circular mean
The thinest arrows are extremes of my interval
I suppose blue point is forecast
The third arrow is circular mean
I need circular density
I've been looking for something similar but I did not found anything.
Any suggestion?
Thanks
To avoid running in the wrong direction would you quickly check if this code goes in the right direction? The arrows can be added easily using +arrow(...) with appropriate loading.
EDIT: One remark to the complicated way of attaching density values - ggplot's geom_density does not seem to like coord_polar (at least the way I tried it).
#create some dummy radial data and wrap it in a dataframe
d1<-runif(100,min=0,max=120)
df = NULL
df$d1 <- d1
df <- as.data.frame(df)
#estimate kernel density and then derive an approximate function to attach density values to the radial values in the dataframe
data_density <- density(d1)
density_function <- with(data_density, approxfun(x, y, rule=1))
df$density <- density_function(df$d1)
#order dataframe to facilitate geom_line in polar coordinates
df <- df[order(df$density,df$d1),]
#ggplot object
require(ggplot2)
g = ggplot(df,aes(x=d1,y=density))
#Radial observations on unit circle
g = g + geom_point(aes(x=d1,y=min(df$density)))
#Density function
g = g + geom_line()
g = g + ylim(0,max(df$density))
g = g + xlim(0,360)
#polar coordinates
g = g + coord_polar()
g
Uniform random variables sampled from (0,120):
Related
I have been trying to use autoplot (in the ggfortify R package) to plot data points in PCA coordinates. For data matrix D2,
autoplot(prcomp(D2),colour=color_codes)
works fine as far a generating a scatterplot of points in the space of principal components 1+2. However, PCA components 1+2 only explain about 30% of the covariance, and I would like to do the same for PCA 1+3, 2+3, and 3+4, etc. Is there a simple argument in autoplot that will let me do this, and if not, what's the simplest function I can use to do so?
Additionally, is there some way to calculate and add centroids using autoplot?
From ?autoplot.prcomp:
autoplot(object, data = NULL, scale = 1, x = 1, y = 2, ...)
where:
x = principal component number used in x axis and
y = principal component number used in y axis
Hence, if you need to plot PC2 vs PC3 and to add the centroid:
library(ggfortify)
set.seed(1)
D2 <- matrix(rnorm(1000),ncol=10)
prcmp <- prcomp(D2)
pc.x <- 2
pc.y <- 3
cnt.x <- mean(prcmp$x[,pc.x])
cnt.y <- mean(prcmp$x[,pc.y])
autoplot(prcmp, x=2, y=3) +
geom_point(x=cnt.x, y=cnt.y, colour="red", size=5)
I wish to compare the observed values to the fitted ones. To do so, I decided to use a plot in R. What I want to do is to plot X vs Y and X vs Y.fitted on the same plot. I have written some code, but it is incomplete. My plot needs to look like this one below. On the plot, circles and crosses represent the observed and fitted values respectively
set.seed(1)
x <- runif(8,0,1)
y <- runif(8,0,1)
y.fitted <- runif(8,0,1)
plot(x,y,pch=1)
plot(x,y.fitted,pch=5)
In your code, the second plot will not add points to the existing plot but create a new one. You can + use the function points to add points to the existing plot.
plot(x, y, pch = 1)
points(x, y.fitted, pch = 4)
running plot the second time will create a new one. You could use points
set.seed(1)
x <- runif(8,0,1)
y <- runif(8,0,1)
y.fitted <- runif(8,0,1)
plot(x,y,pch=1)
points(x,y.fitted,pch=5)
A solution with ggplot2 giving a better and neat graph outlook:
library(ggplot2)
df = data.frame(x=runif(8,0,1),y=runif(8,0,1),y.fitted=runif(8,0,1))
df = melt(df, id=c('x'))
ggplot() + geom_point(aes(x=x,y=value, shape=variable, colour=variable), df)
I am new to R and am struggling to find an answer to what I thought would be a relatively common question. I am creating a world map of a variable using filled.contour. For example:
z=matrix(rnorm(7008),nrow=96)
x=seq(-176.25,180, by=3.75)
y=seq(-90,90, by=2.5)
filled.contour(x,y,z, plot.axes={axis(1); axis(2); map(add=TRUE, interior=FALSE)} )
In which x & y are longitude and latitude, and z is a data matrix. I have spent time applying my own colours and levels, however I want to have a gradient of colour with white assigned as zero. With negative number grading to dark blue and positive to dark red through green and yellow.
I have tried to use the color.scale function from the 'plotrix' package
cellcol=matrix(rep("#000000",7008),nrow=96) # replicating the size of my matrix z
cellcol[z>0]=color.scale(z[z>0], c(0,1,1),c(1,1,0),0) # values above zero grading to red
cellcol[z<0]=color.scale(z[z<0], 0, 0,c(0,1)) # values below zero grading to blue
However now I am stuck. Is this the best way to go about doing this? If so how do I input this into the the filled.contour code above? I'm sure it is simple yet can't get it to work.
Thanks for any help in advance.
I have only managed to achieve what you want using ggplot2.
You can try the following (I submerged the volcano data as an example):
library(ggplot2)
library(reshape2)
## Just an example, I subtract the mean to have positive and negative values for z
dd <- volcano-mean(volcano)
## Creates a data.frame with columns x, y, z
dd <- melt(dd)
names(dd) <- c('x','y','z')
## Does the contour plot
d <- ggplot(dd, aes(x,y,z=z))
d + geom_tile(aes(fill=z)) + scale_fill_gradient2(low="blue", high="red")
I wrote a small function that does what you want to achieve:
myFilled.contour <- function(x = seq(0, 1, length.out = nrow(z)),
y = seq(0, 1, length.out = ncol(z)),
z, nlevels=30, ...) {
ma <- max(abs(z))
lvls <- seq(-ma, ma, length.out = nlevels)
cols <- colorRampPalette(c("blue","white","red")) (nlevels - 1)
filled.contour(x, y, z, plot.axes={axis(1); axis(2)},
col=cols, levels=lvls, ...)
}
Using filled.contour and again the submerged volcano dd:
myFilled.contour(z=d)
Using your data:
myFilled.contour(x,y,z)
Caveat: The legend includes levels not used in the contour plot.
Hope it helps,
alex
I need to plot several data points that are defined as
c(x,y, stdev_x, stdev_y)
as a scatter plot with a representation of their 95% confidence limits, for examples showing the point and one contour around it. Ideally I'd like to plot on oval around the point, but don't know how to do it. I was thinking of building samples and plotting them, adding stat_density2d() but would need to limit the number of contours to 1, and could not figure out how to do it.
require(ggplot2)
n=10000
d <- data.frame(id=rep("A", n),
se=rnorm(n, 0.18,0.02),
sp=rnorm(n, 0.79,0.06) )
g <- ggplot (d, aes(se,sp)) +
scale_x_continuous(limits=c(0,1))+
scale_y_continuous(limits=c(0,1)) +
theme(aspect.ratio=0.6)
g + geom_point(alpha=I(1/50)) +
stat_density2d()
First, saved all your plot as object (changed limits).
g <- ggplot (d, aes(se,sp, group=id)) +
scale_x_continuous(limits=c(0,0.5))+
scale_y_continuous(limits=c(0.5,1)) +
theme(aspect.ratio=0.6) +
geom_point(alpha=I(1/50)) +
stat_density2d()
With function ggplot_build() save all the information used for the plot. Contours are stored in object data[[2]].
gg<-ggplot_build(g)
str(gg$data)
head(gg$data[[2]])
level x y piece group PANEL
1 10 0.1363636 0.7390318 1 1-1 1
2 10 0.1355521 0.7424242 1 1-1 1
3 10 0.1347814 0.7474747 1 1-1 1
4 10 0.1343692 0.7525253 1 1-1 1
5 10 0.1340186 0.7575758 1 1-1 1
6 10 0.1336037 0.7626263 1 1-1 1
There are in total 12 contour lines but to keep only outer line, you should subset only group=="1-1" and replace original information.
gg$data[[2]]<-subset(gg$data[[2]],group=="1-1")
Then use ggplot_gtable() and grid.draw() to get your plot.
p1<-ggplot_gtable(gg)
grid.draw(p1)
latticeExtra provides panel.ellipse is a lattice panel function that computes and draws a confidence ellipsoid from bivariate data, possibly grouped by a third variable.
here I draw the levels 0.65 and 0.95 suing your data.
library(latticeExtra)
xyplot(sp~se,data=d,groups=id,
par.settings = list(plot.symbol = list(cex = 1.1, pch=16)),
panel = function(x,y,...){
panel.xyplot(x, y,alpha=0.2)
panel.ellipse(x, y, lwd = 2, col="green", robust=FALSE, level=0.65,...)
panel.ellipse(x, y, lwd = 2, col="red", robust=TRUE, level=0.95,...)
})
Looks like the stat_ellipse function that you found is really a great solution, but here's another one (non-ggplot), just for the record, using dataEllipse from the car package.
# some sample data
n=10000
g=4
d <- data.frame(ID = unlist(lapply(letters[1:g], function(x) rep(x, n/g))))
d$x <- unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2)))
d$y <- unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2)))
# plot points with 95% normal-probability contour
# default settings...
library(car)
with(d, dataEllipse(x, y, ID, level=0.95, fill=TRUE, fill.alpha=0.1))
# with a little more effort...
# random colours with alpha-blending
d$col <- unlist(lapply(1:g, function (x) rep(rgb(runif(1), runif(1), runif(1), runif(1)),n/g)))
# plot points first
with(d, plot(x,y, col=col, pch="."))
# then ellipses over the top
with(d, dataEllipse(x, y, ID, level=0.95, fill=TRUE, fill.alpha=0.1, plot.points=FALSE, add=TRUE, col=unique(col), ellipse.label=FALSE, center.pch="+"))
Just found the function stat_ellipse() here (and here) and it takes care of this beautifully.
g + geom_point(alpha=I(1/10)) +
stat_ellipse(aes(group=id), color="black")
Different data set, of course:
I don't know anything about the ggplot2 library, but you can draw ellipses with plotrix. Does this plot look anything like what you're asking for?
library(plotrix)
n=10
d <- data.frame(x=runif(n,0,2),y=runif(n,0,2),seX=runif(n,0,0.1),seY=runif(n,0,0.1))
plot(d$x,d$y,pch=16,ylim=c(0,2),xlim=c(0,2))
draw.ellipse(d$x,d$y,d$seX,d$seY)
I have plotted the CCDF as mentioned in question part of the maximum plot points in R? post to get a plot(image1) with this code:
ccdf<-function(duration,density=FALSE)
{
freqs = table(duration)
X = rev(as.numeric(names(freqs)))
Y =cumsum(rev(as.list(freqs)));
data.frame(x=X,count=Y)
}
qplot(x,count,data=ccdf(duration),log='xy')
Now, on the basis of answer by teucer on Howto Plot “Reverse” Cumulative Frequency Graph With ECDF I tried to plot a CCDF using the commands below:
f <- ecdf(duration)
plot(1-f(duration),duration)
I got a plot like image2.
Also I read in from the comments in one of the answers in Plotting CDF of a dataset in R? as CCDF is nothing but 1-ECDF.
I am totally confused about how to get the CCDF of my data.
Image1
Image2
Generate some data and find the ecdf function.
x <- rlnorm(1e5, 5)
ecdf_x <- ecdf(x)
Generate vector at regular intervals over range of x. (EDIT: you want them evenly spaced on a log scale in this case; if you have negative values, then use sample over a linear scale.)
xx <- seq(min(x), max(x), length.out = 1e4)
#or
log_x <- log(x)
xx <- exp(seq(min(log_x), max(log_x), length.out = 1e3))
Create data with x and y coordinates for plot.
dfr <- data.frame(
x = xx,
ecdf = ecdf_x(xx),
ccdf = 1 - ecdf_x(xx)
)
Draw plot.
p_ccdf <- ggplot(dfr, aes(x, ccdf)) +
geom_line() +
scale_x_log10()
p_ccdf
(Also take a look at aes(x, ecdf).)
I used ggplot to get desired ccdf plot of my data as shown below:
>>ecdf_x <- ecdf(x)
>>dfr <- data.frame( ecdf = ecdf_x(x),
>>ccdf = 1 - ecdf_x(x) )
>>p_ccdf <- ggplot(dfr, aes(x, ccdf)) + geom_line() + scale_x_log10()
>>p_ccdf
Sorry for posting it so late.
Thank you all!