Plotting derivatives of normal distribution / Gaussians in R - r

I'm trying to calculate derivatives of Gaussians in R and when I try to specify the mean and standard deviation, R seems to ignore this. For example, the following code works to plot a N(0,1) density and it's first and second derivative.
st_norm <- function(x) dnorm(x,0,1)
first_deriv <- function(x) {}
second_deriv <- function(x) {}
body(first_deriv) <- D(body(st_norm), 'x')
body(second_deriv) <- D(body(first_deriv), 'x')
curve(st_norm, -4, 4, ylim = c(-0.4, 0.4), col = 'blue')
curve(first_deriv, -4, 4, add = T, col = 'red')
curve(second_deriv, -4, 4, add = T, col = 'green')
abline(v=0, h=0)
and this produces the following plot:
But, suppose I wanted to do the exact same but to a N(2,2), then I change the code accordingly to:
different_norm <- function(x) dnorm(x,2,2)
different_first_deriv <- function(x) {}
different_second_deriv <- function(x) {}
body(different_first_deriv) <- D(body(different_norm), 'x')
body(different_second_deriv) <- D(body(different_first_deriv), 'x')
curve(different_norm, -4, 8, ylim = c(-0.4, 0.4), col = 'blue')
curve(different_first_deriv, -4, 8, add = T, col = 'red')
curve(different_second_deriv, -4, 8, add = T, col = 'green')
abline(v=0, h=0)
which produces this plot:
so you can see that it is taking the derivatives of a standard normal, not a N(2,2). If you print out the functions of first_deriv and different_first_deriv, they are equal, even though they are meant to be differentiating different functions.
Does anyone know how to fix this problem so I'm taking derivatives of the specified Gaussian distribution I want?

It works if you use a different formula e.g. try this:
different_norm <- function(x, mean=2, sd=2) dnorm((x-mean)/sd, 0, 1)/sd
If you see the General normal distribution section of https://en.wikipedia.org/wiki/Normal_distribution#Alternative_parameterizations then its a re-parameterisation of the standard normal.
I assume the issue is that the parameters mean and sd don't appear in the formula, and additional args from dnorm aren't passing down for some reason

You can just calculate the derivatives and write it out yourself
dnorm_deriv1 <- function(x, mean = 0, sd = 1) {
return(-((x-mean)/(sd^2))*dnorm(x, mean, sd))
}
dnorm_deriv2 <- function(x, mean = 0, sd = 1) {
return((((x-mean)^2) / (sd^4))*dnorm(x, mean, sd)
- (1/sd^2)*dnorm(x, mean, sd))
}
curve(dnorm, -4, 4, ylim = c(-0.4, 0.4), col = 'blue')
curve(dnorm_deriv1, -4, 4, add = T, col = 'red')
curve(dnorm_deriv2, -4, 4, add = T, col = ' green')
abline(v=0, h=0)
curve(dnorm(x, 2, 2), -4, 8, ylim = c(-0.1, 0.2), col = 'blue')
curve(dnorm_deriv1(x, 2, 2), -4, 8, add = T, col = 'red')
curve(dnorm_deriv2(x, 2, 2), -4, 8, add = T, col = ' green')
abline(v=2, h=0)

Related

How could I conduct meta-analysis on percentage outcomes using R?

My example data is as follows:
df <- data.frame(study = c("Hodaie","Kerrigan","Lee","Andrade","Lim"), SR = c(0.5460, 0.2270, 0.7540, 0.6420, 0.5000), SE = c(12.30, 15.70, 12.80, 13.80, 9.00), Patients = c(5, 5, 3, 6, 4))
I want to conduct the meta-analysis with SR(single group percentage), SE (standard error that I can compute based on sample size and percentage), and patients(sample size for each study), and I hope I could get the following forest plot (I found this example in an article, and they also have one group percentage data, but I can't find which R statement or argument they used):
Could anyone tell me which R statement or argument that I could use to conduct the meta-analysis and generate the forest plot above? Thank you!
I am sure there are plenty of ways to do this using packages but it can be accomplished in base R (and there are likely more elegant solutions using base R). The way I do it is to first build a blank plot much larger than the needed graphing portion, then overlay the relevant elements on it. I find one has more control over it this way. A basic example that could get you started is below. If you are new to R (based on your name NewRUser), I suggest running it line-by-line to see how it all works. Again, this is only one way and there are likely better approaches. Good luck!
Sample Data
#### Sample Data (modified from OP)
df <- data.frame(Study = c("Hodaie","Kerrigan","Lee","Andrade","Lim"),
SR = c(0.5460, 0.2270, 0.7540, 0.6420, 0.5000),
SE = c(12.30, 15.70, 12.80, 13.80, 9.00),
Patients = c(5, 5, 3, 6, 4),
ci_lo = c(30, -8.0, 50, 37, 32),
ci_hi = c(78, 53, 100, 91, 67))
### Set up plotting elements
n.studies <- nrow(df)
yy <- n.studies:1
seqx <- seq(-100, 100, 50)
## blank plot much larger than needed
plot(range(-550, 200), range(0, n.studies), type = 'n', axes = F, xlab = '', ylab = '') #blank plot, much bigger than plotting portion needed
# Set up axes
axis(side = 1, at = seqx, labels = seqx, cex.axis = 1, mgp = c(2, 1.5, 1)) # add axis and label (bottom)
mtext(side = 1, at = 0, 'Seizure Reduction', line = 2.5, cex = 0.85, padj = 1)
axis(side = 3, at = seqx, labels = seqx, cex.axis = 1, mgp = c(2, 1.5, 1)) # add axis and label (top)
mtext(side = 3, at = 0, 'Seizure Reduction', line = 2.5, cex = 0.85, padj = -1)
## add lines and dots
segments(df[, "ci_lo"], yy, df[,"ci_hi"], yy) # add lines
points(df[,"SR"]*100, yy, pch = 19) # add points
segments(x0 = 0, y0 = max(yy), y1 = 0, lty = 3, lwd = 0.75) #vertical line # 0
### Add text information
par(xpd = TRUE)
text(x = -550, y = yy, df[,"Study"], pos = 4)
text(x = -450, y = yy, df[,"SR"]*100, pos = 4)
text(x = -350, y = yy, df[,"SE"], pos = 4)
text(x = -250, y = yy, df[,"Patients"], pos = 4)
text(x = 150, y = yy, paste0(df[,"ci_lo"], "-", df[,"ci_hi"]), pos = 4)
text(x = c(seq(-550, -250, 100), 150), y = max(yy)+0.75,
c(colnames(df)[1:4], "CI"), pos = 4, font = 2)
# Add legend
legend(x = 50, y = 0.5, c("Point estimate", "95% Confidence interval"),
pch = c(19, NA), lty = c(NA, 19), bty = "n", cex = 0.65)

how to plot normal distribution with the same mean but different variance in r

I tried to plot 6 normal distribution figure to display the effect of mean and variance on such a plot,my code is as follow:
par(mfrow=c(3,2),bty = "n") # 3 rows by 2 columns, turn off border
mu <- c(6, 8, 6, 8, 6, 8) #designate the 6 mean values
sigma <- c(3, 3, 2, 2, 1, 1) #designate the 6 sd values
label <- c("(a)","(b)","(c)","(d)","(e)","(f)") #designate the 6 labels of the 6 figures
for(i in 1:length(mu))
{
mu.r <- mu[i]
sigma.r <- sigma[i]
lab.r <- label[i]
x <- seq((mu.r - 4*sigma.r), (mu.r + 4*sigma.r), len = 200)
#designate the starting and ending value of mean
plot(x, dnorm(x, mean = mu.r, sd = sigma.r),axes = F,
type="l",lwd = 2, xlab = lab.r, ylab = "",
main=paste0('mu=',mu.r,', sigma=',sigma.r),
)
axis(1, at = (mu.r - 4*sigma.r) : (mu.r + 4*sigma.r))
abline(v = mu.r, col = "red", lwd = 2.5, lty = "longdash")
}
the figures generated is as follow:
[enter image description here][1]
[1]: https://i.stack.imgur.com/Z4czh.png
You didin't said what exactly was the problem. I assume is that all your graphs look the same. That happens because you set your x axis depending on the variance, you need to leave all the graphs on the same scale in order to compare them. I simply set a arbitrary interval of 7 around the mean:
for(i in 1:length(mu))
{
mu.r <- mu[i]
sigma.r <- sigma[i]
lab.r <- label[i]
x <- (mu.r - 7):(mu.r + 7)
#designate the starting and ending value of mean
plot(x, dnorm(x, mean = mu.r, sd = sigma.r),axes = F,
type="l",lwd = 2, xlab = lab.r, ylab = "",
main=paste0('mu=',mu.r,', sigma=',sigma.r),
)
axis(1, at = x)
abline(v = mu.r, col = "red", lwd = 2.5, lty = "longdash")
}
Output:

R: adding axis titles to non ggplot objects

I am working with the R programming language. Normally when I make plots, I am using the ggplot2 library and the aes() options can be used to label the x-axis and add a title. However this time, I the plots I am making are not ggplot2 objects, and therefore can not be labelled in the same way:
library(MASS)
library(plotly)
a = rnorm(100, 10, 10)
b = rnorm(100, 10, 5)
c = rnorm(100, 5, 10)
d = matrix(a, b, c)
parcoord(d[, c(3, 1, 2)], col = 1 + (0:149) %/% 50)
#error - this is also apparent because the ggplotly() command can not be used.
ggplotly(d)
Does anyone know how to add labels on the x-axis of this plot and some title? Can the ggplotly command be used here?
Thanks
You can use title(), e.g.
library(MASS)
a = rnorm(100, 10, 10)
b = rnorm(100, 10, 5)
c = rnorm(100, 5, 10)
d = matrix(a, b, c)
parcoord(d[, c(3, 1, 2)], col = 1 + (0:149) %/% 50)
title(main = "Plot", xlab = "Variable", ylab = "Values")
axis(side = 2, at = seq(0, 5, 0.1),
tick = TRUE, las = 1)

connecting dots in 2 different data sets in R

I have 2 data sets (DSA and DSB) that contain x & y coordinates
tumor<- data.frame(DSA[,c("X_Parameter","Y_Parameter")])
cells<-data.frame(DSB[,c ("X_Parameter","Y_Parameter")])
plot(cells, xlim=c(1,1300), ylim=c(1,1000), col="red")
par(new=TRUE)
plot(tumor, xlim=c(1,1300), ylim=c(1,1000), col="blue")
the plots make this graph
I want to be able to draw a connecting line from every red dot to every blue dot.
Does anyone know if this can be done. thanks
Sample
DSA=(5,5 6,6 5,6 6,5) DSB=(1,1 10,10 10,1 1,10)
what the plot should look like
Brute-force, perhaps inelegant:
DSA <- data.frame(x = c(5, 6, 5, 6),
y = c(5, 6, 6, 5))
DSB <- data.frame(x = c(1, 10, 10, 1),
y = c(1, 10, 1, 10))
plot(y ~ x, DSB, col = "red")
points(DSA, col = "blue")
for (r in seq_len(nrow(DSA))) {
segments(DSA$x[r], DSA$y[r], DSB$x, DSB$y)
}
Edit: more directly:
nA <- nrow(DSA)
nB <- nrow(DSB)
plot(y ~ x, DSB, col = "red")
points(DSA, col = "blue")
segments(rep(DSA$x, each = nB), rep(DSA$y, each = nB),
rep(DSB$x, times = nA), rep(DSB$y, times = nA))
(I still can't figure out an elegant solution with #42's recommendation for combn or outer.)

Plot normal, left and right skewed distribution in R

I want to create 3 plots for illustration purposes:
- normal distribution
- right skewed distribution
- left skewed distribution
This should be an easy task, but I found only this link, which only shows a normal distribution. How do I do the rest?
If you are not too tied to normal, then I suggest you use beta distribution which can be symmetrical, right skewed or left skewed based on the shape parameters.
hist(rbeta(10000,5,2))
hist(rbeta(10000,2,5))
hist(rbeta(10000,5,5))
Finally I got it working, but with both of your help, but I was relying on this site.
N <- 10000
x <- rnbinom(N, 10, .5)
hist(x,
xlim=c(min(x),max(x)), probability=T, nclass=max(x)-min(x)+1,
col='lightblue', xlab=' ', ylab=' ', axes=F,
main='Positive Skewed')
lines(density(x,bw=1), col='red', lwd=3)
This is also a valid solution:
curve(dbeta(x,8,4),xlim=c(0,1))
title(main="posterior distrobution of p")
just use fGarch package and these functions:
dsnorm(x, mean = 0, sd = 1, xi = 1.5, log = FALSE)
psnorm(q, mean = 0, sd = 1, xi = 1.5)
qsnorm(p, mean = 0, sd = 1, xi = 1.5)
rsnorm(n, mean = 0, sd = 1, xi = 1.5)
** mean, sd, xi location parameter mean, scale parameter sd, skewness parameter xi.
Examples
## snorm -
# Ranbdom Numbers:
par(mfrow = c(2, 2))
set.seed(1953)
r = rsnorm(n = 1000)
plot(r, type = "l", main = "snorm", col = "steelblue")
# Plot empirical density and compare with true density:
hist(r, n = 25, probability = TRUE, border = "white", col = "steelblue")
box()
x = seq(min(r), max(r), length = 201)
lines(x, dsnorm(x), lwd = 2)
# Plot df and compare with true df:
plot(sort(r), (1:1000/1000), main = "Probability", col = "steelblue",
ylab = "Probability")
lines(x, psnorm(x), lwd = 2)
# Compute quantiles:
round(qsnorm(psnorm(q = seq(-1, 5, by = 1))), digits = 6)

Resources