U Aight guys. I am very new to Rstudio only knew about it this week. I am using windows 8 and R studio the newest version and have installed RGui as well.
I am trying to plot a histogram for some data and keep getting this error message, even when I try the code in RGui:
screen(1)
histplot(t(X),"metabolites: Hist")
Error in histplot(t(X), "metabolites: Hist") :
could not find function "ceil"
Why does it ask me for "ceil" what does this mean? I just want to plot my histogram?
My data is represented in 4 rows by 200 columns and in the first column is 4 different names of variables. I.e. each row represents data from a different variable.
I am thinking its because I would need to do a histogram for each row separately rather than trying to do a histogram for all data. Could this be the reason the error is coming up?
I am using the package histplot.r, here is the script for histplot:
histplot <- function(x,sam) {
nn <- ceil(sqrt(length(x)))
BW <- (max(x)-min(x))/nn
xxx <- hist(x, freq = TRUE, main=sam)
N <- xxx$counts # Get the freq distribution
MIDS <- xxx$mids # Get the centres
Xaxis <- seq(min(x), max(x), by = 0.01)
MU <- mean(x)
SIGMA <- std(x)
y <- exp(-0.5 * ((Xaxis - MU)/SIGMA)^2) / (sqrt(2*pi) * SIGMA)
matplot(Xaxis, (y * BW * sum(N)), type="l", col = 2, lty = 1, lwd = 1, add = TRUE)
abline(a=NULL,b=NULL, h=NULL, v=MU, col=3, lty=2, lwd=1) # Add mean
abline(a=NULL,b=NULL, h=NULL, v=MU-SIGMA, col=4, lty=2, lwd=1) # Add mean-stdev
abline(a=NULL,b=NULL, h=NULL, v=MU+SIGMA, col=4, lty=2, lwd=1) # Add mean+stdev
}
The histplot didn't work when I run it in my script in Rstudio, screen 1. Here is my full script:
rm(list=ls())
graphics.off()
source("histplot.r")
source("normplot.r")
X <- read.table("metabolites.csv",sep=",",header=FALSE)
x11()
split.screen(c(1,2))
screen(1)
histplot (t(X), "Metabolites: Hist")
screen(2)
bbb <- qqplot(t(X), ppoints(t(X)), ylab =
"Probability", main = "metabolites: Norm")
qqplot(bbb)
The ceil function is a function that histplot uses under the hood. It is not part of a standard R install, and not part of any of the additional packages you loaded. This leads to the error you get, it cannot find the ceil function. I suspect the ceil function has the same functionality as the ceiling function, but I'm just speculating here.
Probably the ceil function is part of a package on which the histplot package depends. Try reinstalling the package with dependencies = TRUE. From your comment it turned out you needed to also load the matlab package, which contains the ceil function.
I believe the ceil function is in the pracma library
https://www.rdocumentation.org/packages/pracma/versions/1.9.9/topics/ceil
Related
So I used the plotrix library to plot a histogram using some weights , the histogram shows up as expected but when I tried a plot the mean as a vertical line it won't show up at all
Here's a snippet of my code:
library("plotrix")
library("zoom")
vals = seq.int(from = 52.5 , to = 97.5 , by = 5)
weights <- c(18.01,18.26,16.42,14.07,11.67,9.19,6.46,3.85,1.71,0.34)/100
mean <- sum(vals*weights)
wh <- weighted.hist(x = vals , w = weights , freq = FALSE)
abline(v = mean)
the abline() seems to work only with the normal hist() function
I am sorry if the question sounds stupid , I am R newbie however I did my research and could not find any helpful info.
Thanks in advance.
You should provide a sample of your data. Your calculation of the weighted mean is only correct if your weights sum to 1. If they do not, you should use weighted.mean(vals, weights) or sum(vals * weights/sum(weights)). The following example is slightly modified from the one on the weighted.hist manual page (help(weighted.hist)):
vals <- sample(1:10, 300, TRUE)
weights <- (101:400)/100
weighted.hist(vals, weights, breaks=1:10, main="Test weighted histogram")
(mean <- weighted.mean(vals, weights))
# [1] 5.246374
The histogram starts at 1, but this is 0 on the x-axis coordinates so we need to subtract 1 to get the line in the right place:
abline(v=mean-1, col="red")
Using your data we need to identify the first boundary to adjust the mean so it plots in the correct location"
wh$breaks[1]
# [1] 52.5
abline(v=mean - wh$breaks[1], col="red")
It would be convenient to interactively select a decent viewpoint using rgl and then adopt the same orientation in a lattice 3d-plot. For example, given the following plot using a non-informative viewpoint.
library(lattice)
wireframe(volcano, screen = list(x=0, y=0, z=0))
The same can be opened in rgl by
library(rgl)
persp3d(volcano)
view3d(0, 0)
Interactively it is easy to rotate the plot to an informative view.
The matrix giving the current rgl viewpoint in can be extracted by
p <- par3d()
p$userMatrix
How can this matrix be converted into corresponding x,y,z screen parameters to replicate the view in lattice?
UPDATE 1
I tried out 42's conversion below. The code shows the rgl plot and the corresponding lattice plot per row. If I implemented it correctly (see code below), there appears to still be an issue.
# convert rgl viewpoint into lattice
# screen orientation
rgl_to_lattice_viewpoint <- function()
{
p <- par3d()
rotm <- p$userMatrix
B = 360*atan(rotm[1,2]/rotm[2,2])/(2*pi)
P = 360*asin(-rotm[3,2])/(2*pi)
H = 360*atan(rotm[3,1]/rotm[3,3])/(2*pi)
list(x=-B, y=-P, z=-H)
}
# read and plot PNG image
plot_png <- function(f)
{
img <- readPNG(f)
rimg <- as.raster(img) # raster multilayer object
plot(NULL, xlim=c(0,1), ylim=c(0,1), xlab = "", ylab = "",
asp=1, frame=F, xaxt="n", yaxt="n")
rasterImage(rimg, 0, 0, 1, 1)
}
# create rgl snapshot with random rotation and
# corresponding lattice wireframe plot
lattice_plus_rgl_plot <- function()
{
# rgl plot random rotation
persp3d(volcano, col = "green3")
theta <- sample(-180:180, 1)
phi <- sample(-90:90, 1)
view3d(theta, phi, fov=40)
v <- rgl_to_lattice_viewpoint()
f <- tempfile(fileext = ".png")
rgl.snapshot(f)
rgl.close()
# lattice plot
f2 <- tempfile(fileext = ".png")
png(f2)
print(wireframe(volcano, screen = v))
dev.off()
# plot both
plot_png(f)
plot_png(f2)
}
# CREATE SOME PLOTS
library(rgl)
library(lattice)
library(png)
par(mfrow=c(3,2), mar=c(0,0,0,0))
replicate(3, lattice_plus_rgl_plot())
I used the answer to this question for conversion from a rotation matrix to angles: Conversion euler to matrix and matrix to euler . I admit to concern that I see another somewhat different answer here: How to calculate the angle from Roational matrix . (My linear algebra is not good enough to determine which of these is correct.)
p <- par3d()
rotm <- p$userMatrix
B = 360*atan(rotm[1,2]/rotm[2,2])/(2*pi)
P = 360*asin(-rotm[3,2])/(2*pi)
H = 360*atan(rotm[3,1]/rotm[3,3])/(2*pi)
> print(list(B,P,H))
[[1]]
[1] 41.54071
[[2]]
[1] 40.28412
[[3]]
[1] 41.24902
At that point I had already rotated the RGL-object to roughly the "viewing point" that you had suggested. I discovered by experimentation that the negative values supplied to the wireframe call delivered apparently correct results. "Viewer rotation angles" are plausibly seen as the negative for "object rotation angles".
png(); print(wireframe(volcano, screen = list(x=-B, y=-P, z=-H)) ); dev.off()
There is a rotate.wireframe function in the TeachingDemos package but it does not play well with concurrently running rgl plots. (No plot was apparent until I closed the rgl device.) It also seemed kind of buggy when running on a Mac (thick black line across the lattice plot). It uses the X11/XQuartz facilities to manage interaction via tk/tcl functions and I was unable to reproduce the plots from the angles being displayed. Looking at the code I'm not able to understand why that should be so. But your mileage may vary.
This version of your function uses conversions from the orientlib package, and makes the rotation matrix an argument:
rgl_to_lattice_viewpoint <- function(rotm = par3d("userMatrix"))
{
e <- -orientlib::eulerzyx(orientlib::rotmatrix(rotm[1:3, 1:3]))#x*180/pi
list(z = e[1], y = e[2], x = e[3])
}
Note that the z, y, x order is essential.
Using it in place of your function, I get this output:
These get the rotation right. I don't know if it's also possible to get the perspective to match.
Edited to add: rgl version 0.95.1468, so far available only on R-forge,
contains a version of this function and one for base graphics as well.
I can't seem to get the ksmooth function or KernSmooth package to give me anything for the following example:
x <- 1:100
y <- 3*sin(x/10)+rnorm(100)
plot(x,y)
Which looks like this:
The ksmooth function does nothing and just gives me back the same points. Using the KernSmooth package all I can seem to get is a linear approximation.
Why does ksmooth(x,y,kernel="normal",bandwidth=0.5) just give me back the same points? Also how do I use the KernSmooth package? Thanks.
Your selected bandwidth = 0.5 is too small.
x <- 1:100
y <- 3*sin(x/10)+rnorm(100)
plot(x,y)
lines(ksmooth(x, y, "normal", bandwidth = 5), col = "red")
library(KernSmooth)
fit <- locpoly(x, y, bandwidth = 5)
lines(fit, col = "blue")
I want to create a contour of variable z with the x,y,z data. However, it seems like we need to provide the data in increasing order.
I tried to use some code but it gave me the error.
I tried the following code: Trial 1:
age2100 <- read.table("temp.csv",header=TRUE,sep=",")
x <- age2100$x
y <- age2100$y
z <- age2100$z
contour(x,y,z,add=TRUE,col="black")
I got the following error
Error in contour.default(x, y, z, add = TRUE, col = "black") : increasing 'x' and 'y' values expected
I then tried to use ggplot2 to create the contour. I used the following code:
library("ggplot2")
library("MASS")
library("rgdal")
library("gpclib")
library("maptools")
age2100 <- read.table("temp.csv",header=TRUE,sep=",")
v <- ggplot(age2100, aes(age2100$x, age2100$y,z=age2100$z))+geom_contour()
v
I got the following error:
Warning message:
Not possible to generate contour data
Please find the data on the following location https://www.dropbox.com/s/mg2bo4rcr6n3dks/temp.csv
Can anybody tell me how to create the contour data from the third variable (z) from the temp.csv ? I need to do these many times so I am trying to do on R instead of Arcgis.
Here is an example of how one interpolates using interp from the akimapackage:
age2100 <- read.table("temp.csv",header=TRUE,sep=",")
x <- age2100$x
y <- age2100$y
z <- age2100$z
require(akima)
fld <- interp(x,y,z)
par(mar=c(5,5,1,1))
filled.contour(fld)
Here is an alternate plot using the imagefunction (this allows some flexibility to adding lower level plotting functions (requires the image.scale function, found here):
source("image.scale.R") # http://menugget.blogspot.de/2011/08/adding-scale-to-image-plot.html
x11(width=5, height=6)
layout(matrix(c(1,2), nrow=1, ncol=2), widths=c(4,1), height=6, respect=TRUE)
layout.show(2)
par(mar=c(4,4,1,1))
image(fld)
contour(fld, add=TRUE)
points(age2100$x,age2100$y, pch=".", cex=2)
par(mar=c(4,0,1,4))
image.scale(fld$z, xlab="", ylab="", xaxt="n", yaxt="n", horiz=FALSE)
box()
axis(4)
mtext("text", side=4, line=2.5)
I'd like to superpose a histogram and an xyplot representing the cumulative distribution function using r's lattice package.
I've tried to accomplish this with custom panel functions, but can't seem to get it right--I'm getting hung up on one plot being univariate and one being bivariate I think.
Here's an example with the two plots I want stacked vertically:
set.seed(1)
x <- rnorm(100, 0, 1)
discrete.cdf <- function(x, decreasing=FALSE){
x <- x[order(x,decreasing=FALSE)]
result <- data.frame(rank=1:length(x),x=x)
result$cdf <- result$rank/nrow(result)
return(result)
}
my.df <- discrete.cdf(x)
chart.hist <- histogram(~x, data=my.df, xlab="")
chart.cdf <- xyplot(100*cdf~x, data=my.df, type="s",
ylab="Cumulative Percent of Total")
graphics.off()
trellis.device(width = 6, height = 8)
print(chart.hist, split = c(1,1,1,2), more = TRUE)
print(chart.cdf, split = c(1,2,1,2))
I'd like these superposed in the same frame, rather than stacked.
The following code doesn't work, nor do any of the simple variations of it that I have tried:
xyplot(cdf~x,data=cdf,
panel=function(...){
panel.xyplot(...)
panel.histogram(~x)
})
You were on the right track with your custom panel function. The trick is passing the correct arguments to the panel.- functions. For panel.histogram, this means not passing a formula and supplying an appropriate value to the breaks argument:
EDIT Proper percent values on y-axis and type of plots
xyplot(100*cdf~x,data=my.df,
panel=function(...){
panel.histogram(..., breaks = do.breaks(range(x), nint = 8),
type = "percent")
panel.xyplot(..., type = "s")
})
This answer is just a placeholder until a better answer comes.
The hist() function from the graphics package has an option called add. The following does what you want in the "classical" way:
plot( my.df$x, my.df$cdf * 100, type= "l" )
hist( my.df$x, add= T )