With Mathematica I made a plot.
With R this plot can be made to look more elegant, I guess.
How can I make such a plot in R?
It is about the function M_{\pm}
M^2_\pm = \frac{y \pm \sqrt{14x + 6xy + y^2}}{2x}
The following is show on the plot
The curve M^2_+ = M_-
The curve M^2_+ = 0
The curve M^2_- = 0
The shaded region where both M^2_+ and M^2_- > 0
Some points with text
In the new plot
The axes should be on the outside of the plot as is usual in R
I would welcome a more elegant alternative for the text and the arrows in the pictures
P.S. With the help pages of R I tried to make such a plot, but I didn't get beyond the basic use of plot and curve.
Update Maybe contour can do the job
You could do something like this:
f <- function(x,y){x*y}
x <- seq(0.2,2,length=1000)
objective <- 0.5
y <- c()
for(i in 1:length(x)){
y[i] <- optimize(function(y){abs(f(x[i],y)-objective)},interval=c(0,4))$minimum
}
plot(x,y,type="l")
This plot shows where the function x*y=0.5 for x between 0.2 and 2. This isn't for your particular function, but I hope it's a useful start. Note that this is very hacky since optimize is slow and for loops should generally be avoided in R whenever possible.
Related
I have 10 matrices where each one represent the eigenvalues of correlation matrices of wavelet coefficients of a number of time series.
I would like to generate a heatmap of my data to see if there are any overlapping significant events across the different scales.
So far I have hacked together the following image using the graphics package as described here by #Josliber.
I am still getting to grips with R so excuse the nasty code but it works for me for now. I have yet to mess around with the labels and formatting but it's a quick and dirty representation.
#plotting the eigenvalues for each of the wavelet coefficient scales
w1mat <- matrix(w1eigen[1,])
w2mat <- matrix(w2eigen[1,])
w3mat <- matrix(w3eigen[1,])
w4mat <- matrix(w4eigen[1,])
w5mat <- matrix(w5eigen[1,])
w6mat <- matrix(w6eigen[1,])
w7mat <- matrix(w7eigen[1,])
w8mat <- matrix(w8eigen[1,])
w9mat <- matrix(w9eigen[1,])
w10mat <- matrix(w10eigen[1,])
#plots the eigenvalues for each of the scales
par(mfrow=c(10,1))
imageW1 <- image(w1mat)
imageW2 <- image(w2mat)
imageW3 <- image(w3mat)
imageW4 <- image(w4mat)
imageW5 <- image(w5mat)
imageW6 <- image(w6mat)
imageW7 <- image(w7mat)
imageW8 <- image(w8mat)
imageW9 <- image(w9mat)
imageW10 <- image(w10mat)
As you can see I used the image function in the graphics package to create this and I am sure I can achieve the same in ggplot with greater control.
Ultimately I wish to create a plot similar to the one below where there is a common Y axis and they're sitting right on top of one another with no white space.
What I would like to know is whether using the stacked image function in graphics is the best approach or is there a better way to visualise the data in an alternative package?
So, I am able to use the plot() function in R to graph different functions. However, I am finding that the graphs in R do not typically show the entire curve of the function. Let me use an example:
fun <- function(x){
x^3 + 2*x^2 + 3*x + 4
}
plot(fun)
However, when I plot the same function using the Desmos Graphing Calculator it shows all four quadrants of the Cartesian graph whereas R is only showing one:
My question: How can I modify RPlot to show all four quadrants as opposed to just one as in the above case?
I think you can do this just by extending the default range (which is [0,1]):
plot(fun,from=-5,to=5,ylim=c(-8,8),col="red")
grid()
abline(v=0,h=0,lty=2)
I've added a few frills to make it look a little more like the desired plot. Adding a point on the y axis is easy; adding the x-intercept is not quite so easy.
points(0,fun(0),pch=16)
points(Re(polyroot(c(4,3,2,1))[2]),0,pch=16)
I've followed the instructions on this website from STHDA to plot correlation matrices and correlograms in R. The website and examples are really good. However, I'd like to plot the upper part of the correlogram over the upper part of the correlation matrix.
Here's the code:
library(PerformanceAnalytics)
chart.Correlation(mtcars, histogram=TRUE, pch=19)
This should give me the correlation matrix using scatter plots, together with the histogram, which I'd like to maintain. But for the upper part of the plot, I'd like to have the correlogram obtained from this code:
library(corrplot)
corrplot(cor(mtcars), type="upper", order="hclust", tl.col="black", tl.srt=45)
The obvious way of doing it is exporting all graphs in pdf and then work with Inkscape, but it would be nicer if I could get this directly from R. Is there any possible way for doing this?
Thanks.
The trick to using the panel functions within pairs is found in help(pairs):
A panel function should not attempt to start a new plot, but just plot within a given coordinate system: thus 'plot' and 'boxplot' are not panel functions.
So, you should use graphic-adding functions, such as points, lines, polygon, or perhaps (when available) plot(..., add=TRUE), but not a straight-up plot. What you were suggesting in your comment (with SpatialPolygons) might have worked with some prodding if you actually tried to plot it on a device vice just returning it from your plotting function.
In my example below, I actually do "create a new plot", but I cheat (based on this SO post) by adding a second plot on top of the one already there. I do this to shortcut an otherwise necessary scale/shift, which would still not be perfect since you appear to want a "perfect circle", something that can really only be guaranteed with asp=1 (aspect ratio fixed at 1:1).
colorRange <- c('#69091e', '#e37f65', 'white', '#aed2e6', '#042f60')
## colorRamp() returns a function which takes as an argument a number
## on [0,1] and returns a color in the gradient in colorRange
myColorRampFunc <- colorRamp(colorRange)
panel.cor <- function(w, z, ...) {
correlation <- cor(w, z)
## because the func needs [0,1] and cor gives [-1,1], we need to
## shift and scale it
col <- rgb( myColorRampFunc( (1+correlation)/2 )/255 )
## square it to avoid visual bias due to "area vs diameter"
radius <- sqrt(abs(correlation))
radians <- seq(0, 2*pi, len=50) # 50 is arbitrary
x <- radius * cos(radians)
y <- radius * sin(radians)
## make them full loops
x <- c(x, tail(x,n=1))
y <- c(y, tail(y,n=1))
## I trick the "don't create a new plot" thing by following the
## advice here: http://www.r-bloggers.com/multiple-y-axis-in-a-r-plot/
## This allows
par(new=TRUE)
plot(0, type='n', xlim=c(-1,1), ylim=c(-1,1), axes=FALSE, asp=1)
polygon(x, y, border=col, col=col)
}
pairs(mtcars, upper.panel=panel.cor)
You can manipulate the size of the circles -- at the expense of unbiased visualization -- by playing with the radius. The colors I took directly from the page you linked to originally.
Similar functions can be used for your lower and diagonal panels.
I'm looking for some technique in R similiar to command hold all in Matlab.
In Matlab I generate some data:
x = normrnd(0,1,1000,1);
[a,b]=hist(x,20);
L=b(2)-b(1);
area=sum(L*a);
frequency=a/area;
bar(b,frequency,1);
hold all;
range=b(1):0.1:b(20);
f1=normpdf(range,0,1);
f2=normpdf(range,2,2);
plot1=plot(range,f1,'r');
plot2=plot(range,f2,'m');
hold off;
I would like to create something similiar in R. I've tried this way:
x <- rnorm(1000)
h <- hist(x, breaks = 20)
a <- h$counts
b <- h$mids
L <- b[2] - b[1]
area <- sum(L*a)
frequency = a/area
range <- seq(b[1],b[20], by = 0.1)
f1 <- dnorm(range,0,1)
f2 <- dnorm(range,2,2)
barplot(frequency, names.arg = c(b))
And I stopped here, since I don't know how to add another graph to current plot. I tried to use ggplot2, but I haven't much experience with that and I failed on creating barplot with this library.
If there is a way to do that with ggplot2, I would like to know it with explanation, since I want to learn it. I will appreciate solution with traditional plot system aswell.
P.S. I used barplot(frequency, names.arg = c(b)), because I read here, that there is no equivalent in R for Matlab's bar function.
Sometimes it is better to tell us what you are trying to do, rather than how you are trying to do it. From the looks of your R code your boxplot is just a scaled histogram and from the other R code and my guesses from the matlab code you want to add reference lines for normal distributions. If I am correct then you are going about this the long way in R. The following R code is much simpler:
x <- rnorm(1000)
hist(x, prob=TRUE)
curve(dnorm(x,0,1), add=TRUE)
curve(dnorm(x,2,2), add=TRUE)
Even better would be to add col='blue' or similar to the curve calls. If you really feel the need to choose your own x values then you can replace the calls to curve with:
lines(range, dnorm(range, 0, 1) )
lines(range, dnorm(range, 2, 2) )
If you really want to learn to add lines to a barplot then you should realize that the default locations for bars may not be what you expect. Look at the updateusr function in the TeachingDemos package for R for examples of adding lines to a barplot.
I'm trying to plot some data with 2d density contours using ggplot2 in R.
I'm getting one slightly odd result.
First I set up my ggplot object:
p <- ggplot(data, aes(x=Distance,y=Rate, colour = Company))
I then plot this with geom_points and geom_density2d. I want geom_density2d to be weighted based on the organisation's size (OrgSize variable). However when I add OrgSize as a weighting variable nothing changes in the plot:
This:
p+geom_point()+geom_density2d()
Gives an identical plot to this:
p+geom_point()+geom_density2d(aes(weight = OrgSize))
However, if I do the same with a loess line using geom_smooth, the weighting does make a clear difference.
This:
p+geom_point()+geom_smooth()
Gives a different plot to this:
p+geom_point()+geom_smooth(aes(weight=OrgSize))
I was wondering if I'm using density2d inappropriately, should I instead be using contour and supplying OrgSize as the 'height'? If so then why does geom_density2d accept a weighting factor?
Code below:
require(ggplot2)
Company <- c("One","One","One","One","One","Two","Two","Two","Two","Two")
Store <- c(1,2,3,4,5,6,7,8,9,10)
Distance <- c(1.5,1.6,1.8,5.8,4.2,4.3,6.5,4.9,7.4,7.2)
Rate <- c(0.1,0.3,0.2,0.4,0.4,0.5,0.6,0.7,0.8,0.9)
OrgSize <- c(500,1000,200,300,1500,800,50,1000,75,800)
data <- data.frame(Company,Store,Distance,Rate,OrgSize)
p <- ggplot(data, aes(x=Distance,y=Rate))
# Difference is apparent between these two
p+geom_point()+geom_smooth()
p+geom_point()+geom_smooth(aes(weight = OrgSize))
# Difference is not apparent between these two
p+geom_point()+geom_density2d()
p+geom_point()+geom_density2d(aes(weight = OrgSize))
geom_density2d is "accepting" the weight parameter, but then not passing to MASS::kde2d, since that function has no weights. As a consequence, you will need to use a different 2d-density method.
(I realize my answer is not addressing why the help page says that geom_density2d "understands" the weight argument, but when I have tried to calculate weighted 2D-KDEs, I have needed to use other packages besides MASS. Maybe this is a TODO that #hadley put in the help page that then got overlooked?)