I am trying to plot the beta-gumbel distribution using R(software) by the following,
The genreal idea is that, in the pdf of beta distribution, instead of plugging in x, we use the cdf of gumbel instead. But I couldn't get the right plot.
x <- seq(-3, 3, length=100)
Fx = pgumbel(x,loc=0,scale=1)
y = dbeta(Fx,shape1=0.5,shape2=0.5)
plot(x, y, type="l", lty=2, xlab="x value", ylab="Density",ylim=c(0,1))
I don't believe you when you say that you didn't use any add-on packages: pgumbel() is not in base R. library("sos"); findFn("pgumbel") finds it in a variety of places, I used the evd package.
There are a couple of small issues here.
library("evd")
The main thing is that you want length=100 rather than by=100 (which gives you a single-element x vector):
x <- seq(-3, 3, length=100)
The actual computations are OK:
Fx = pgumbel(x,loc=0,scale=1)
y = dbeta(Fx,shape1=0.5,shape2=0.5)
You need to change ylim to be able to see what's going on. However, I also think you need to do something to account for the differential dx in order to get a proper density function (that's more of a StackExchange than a StackOverflow question though).
par(las=1,bty="l") ## my personal preferences
plot(x, y, type="l", lty=2, xlab="x value", ylab="Density",ylim=c(0,40))
Related
R will automatically determine the plot ranges (xlim, ylim) from the first plot() call. But when you are plotting multiple things on a single plot, the subsequent calls to plot() might not fit in the frame, as in this case:
mu <- 8
sd <- 8
plot(function (x) dnorm(x, mu, sd, log = TRUE), xlim = c(0, 10)) # log likelihood
plot(function (x) (mu-x)/sd^2, col = "green", add = TRUE, xlim = c(0, 10)) # derivative log likelihood
I know I could first determine the ranges of all plot components myself and then min and max them together and pass the range to the first plot() call... but it is sooo inconvenient... and results in R scripts which are bulky and not easy to read.
Is there some simple way to handle this in R, am I missing something? I am sure libraries like ggplot or lattice have better solutions, would be interesting to see them, but I strongly prefer solution with the base R. Thanks! :)
EDIT: is it possible something like to defer the plotting of the plot until I call the last plot() and then plot everything? :-) This could be very elegant and the code would stay nicely compact :)
You could adapt your approach a little and define the functions beforehand.
fun1 <- function(x) dnorm(x, mu, sd, log=TRUE)
fun2 <- function(x) (mu-x)/sd^2
Then you easily may calculate the range of everything in the desired xlim of the plot – here 0:10.
y.range <- range(sapply(0:10, function(x) c(fun1(x), fun2(x))))
Finally rather use the already defined functions than repeat them in the plot() call. NB you may be looking for curve(), but it also works with plot() in this case.
curve(fun1, xlim=c(0, 10), ylim=y.range)
curve(fun2, col="green", add=TRUE, xlim=c(0, 10))
How about something along this line:
plot(function (x) dnorm(x, mu, sd, log = TRUE), xlim = c(0, 10)) # log likelihood
par(new=TRUE)
plot.function(function (x) (mu-x)/sd^2, col = "green", axes=FALSE, ann=FALSE) # derivative log
axis(side = 4)
Output
I'm doing stochastic dominance analysis with diferent income distributions using Pen's Parade. I can plot a single Pen's Parade using Pen function from ineq package, but I need a visual comparison and I want multiple lines in the same image. I don't know how extract values from the function, so I can't do this.
I have the following reproducible example:
set.seed(123)
x <- rnorm(100)
y <- rnorm(100, mean = 0.2)
library(ineq)
Pen(x)
Pen(y)
I obtain the following plots:
I want obtain sometime as the following:
You can use add = TRUE:
set.seed(123)
x <- rnorm(100)
y <- rnorm(100, mean = 0.2)
library(ineq)
Pen(x); Pen(y, add = TRUE)
From help("Pen"):
add logical. Should the plot be added to an existing plot?
While the solution mentioned by M-M in the comments is a more general solution, in this specific case it produces a busy Y axis:
Pen(x)
par(new = TRUE)
Pen(y)
I would generalize the advice for plotting functions in this way:
Check the plotting function's help file. If it has an add argument, use that.
Otherwise, use the par(new = TRUE) technique
Update
As M-M helpfully mentions in the comments, their more general solution will not produce a busy Y axis if you manually suppress the Y axis on the second plot:
Pen(x)
par(new = TRUE)
Pen(y, yaxt = "n")
Looking at ?ineq::Pen() it seems to work like plot(); therefore, followings work for you.
Pen(x)
Pen(y, add=T)
Note: However, add=T cuts out part of your data since second plot has points which fall out of the limit of the first.
Update on using par(new=T):
Using par(new=T) basically means overlaying two plots on top of each other; hence, it is important to make them with the same scale. We can achieve that by setting the same axis limits. That said, while using add=T argument it is desired to set limits of the axis to not loose any part of data. This is the best practice for overlaying two plots.
Pen(x, ylim=c(0,38), xlim=c(0,1))
par(new=T)
Pen(y, col="red", ylim=c(0,38), xlim=c(0,1), yaxt='n', xaxt='n')
Essentially, you can do the same with add=T.
Having trouble creating a plot of different power functions for different alpha levels. This is what I have currently but I cannot figure out how to create the multiple lines representing the smooth power function across different alpha levels:
d <- data.frame()
for (s in seq(0,.5,.05)) {
for (n in seq(20,500,by=20)){
d <- rbind(d,power.t.test(n=n,delta = 11,sig.level=s,sd= 22.9))
}
}
d$sig.level.factor <-as.factor(d$sig.level)
plot(d$power~d$n, col=d$sig.level.factor)
for i in length(sig.level.factor){
lines(d$n[d$sig.level.factor==d$sig.level.factor[i]],d$power[d$sig.level.factor==d$sig.level.factor[i]], type="l", lwd=2, col=colors[n])
}
for (i in 1:length(seq(0,.5,.05))){
lines(d$n[d$sig.level.factor==d$sig.level[i]], d$power, type="l", lwd=2, col=colors[i])
}
for (i in 1:length(d$sig.level.factor)){
lines(d$n[d$sig.level.factor==i], d$power[d$sig.level.factor==i], type="l", lwd=2, col=colors[i])
}
My goal is to create the lines that will show the smooth curves connecting all the points that contain equivalent alpha values across different sample sizes.
Slightly late answer but hope you can still use it. You can create a matrix of results over n and significance levels using sapply and then plot everything in one go using the super useful function matplot:
n <- seq(20, 300, by=10)
alphas <- seq(0, .25, .05)
res <- sapply(alphas, function(s) {power.t.test(n=n, delta=11, sig.level=s, sd= 22.9)$power})
matplot(n, res, type="l", xlab="Sample size", ylab="Power")
There is one annoying "feature" of power.t.test and power.prop.test and that is that it is not fully vectorized over all arguments. However, your situation, where the output is the power makes it easier.
I am having trouble understanding the Beta function in R. I want the y scale to display a relative value in percent (0->1). How do I achive this with the graph having the same form?
x = seq(0,1,0.001)
plot(x,dbeta(x,10,40), type="l", col="red", xlab="time", ylab="frequency")
It sounds like you're looking for the beta density, normalized so the maximum value is 1. This could be accomplished with:
x = seq(0,1,0.001)
density = dbeta(x, 10, 40)
plot(x, density/max(density), type="l", col="red", xlab="time", ylab="frequency")
Well, I am sure you looked the help page at the value page perhaps there is what you are looking for :
dbeta gives the density, pbeta the distribution function, qbeta the quantile function, and rbeta generates random deviates.
I think you want to plot the pbeta
I am using filled.contour() to plot data stored in a matrix. The data is generated by a (highly) non-linear function, hence its distribution is not uniform at all and the range is very large.
Consequently, I have to use the option "levels" to fine tune the plot. However, filled.contour() does not use these custom levels to make an appropriate color key for the heat map, which I find quite surprising.
Here is a simple example of what I mean:
x = c(20:200/100)
y = c(20:200/100)
z = as.matrix(exp(x^2)) %*% exp(y^2)
filled.contour(x=x,y=y,z=z,color.palette=colorRampPalette(c('green','yellow','red')),levels=c(1:60/3,30,50,150,250,1000,3000))
As you can see, the color key produced with the code above is pretty much useless. I would like to use some sort of projection (perhaps sin(x) or tanh(x)?), so that the upper range is not over-represented in the key (in a linear way).
At this point, I would like to:
1) know if there is something very simple/obvious I am missing, e.g.: an option to make this "key range adapting" automagically;
2) seek suggestions/help on how to do it myself, should the answer to 1) be negative.
Thanks a lot!
PS: I apologize for my English, which is far from perfect. Please let me know if you need me to clarify anything.
I feel your frustration. I never found a way to do this with filled contour, so have usually reverted to using image and then adding my own scale as a separate plot. I wrote the function image.scale to help out with this (link). Below is an example of how you can supply a log-transform to your scale in order to stretch out the small values - then label the scale with the non-log-transformed values as labels:
Example:
source("image.scale.R") # http://menugget.blogspot.de/2011/08/adding-scale-to-image-plot.html
x = c(20:200/100)
y = c(20:200/100)
z = as.matrix(exp(x^2)) %*% exp(y^2)
pal <- colorRampPalette(c('green','yellow','red'))
breaks <- c(1:60/3,30,50,150,250,1000,3000)
ncolors <- length(breaks)-1
labs <- c(0.5, 1, 3,30,50,150,250,1000,3000)
#x11(width=6, height=6)
layout(matrix(1:2, nrow=1, ncol=2), widths=c(5,1), heights=c(6))
layout.show(2)
par(mar=c(5,5,1,1))
image(x=x,y=y,z=log(z), col=pal(ncolors), breaks=log(breaks))
box()
par(mar=c(5,0,1,4))
image.scale(log(z), col=pal(ncolors), breaks=log(breaks), horiz=FALSE, xlab="", ylab="", xaxt="n", yaxt="n")
axis(4, at=log(labs), labels=labs)
box()
Result: