I am trying to do a for loop like this:
for (n in 1:200)
{
pre[n] <- aggregate(S[n]~Secs[n], data = dataframe, FUN = sum)
freqsdf[n] <- data.frame(table(SecsOnly2$Secs[n]))
AVAL[n] <- pre[n]$S[n]/freqsdf[n]$Freq
AVAL[n] <- data.frame(AVAL[n])
hist(dataframe$Secs[n], xlab = "", ylab = "", ylim = c(0, 16000), axes = FALSE, col = "grey")
axis(4, ylim = c(0, 16000), col = "black", col.axis = "black", las = 2, cex.axis = .5)
par(new = TRUE)
plot(pre[n]$Secs[n], AVAL[n], col = "red" , type = "l")
abline(h = 0.25) }
But I'm getting this error:
Error in eval(expr, envir, enclos) : object 'S' not found
My dataset that has the "S" variable has a bunch of variables including "S1" through "S200." I want R to go through all this code for all the "S" variables, the "Secs" variables, etc... This code worked fine for just S1, when I wrote it just for S1, Secs1, etc...(not in a loop). But I want R to go through the same code for all my columns. I'm not sure why "S" is not being found. I thought by going from n = 1 to n = 200, R automatically looks for "S1", "Secs1," etc... the first time the loop runs, and then "S2", "Secs2," etc... the second time it runs, and so on.
In this line (and several other places):
pre[n]$S[n]/freqsdf[n]$Freq
You are trying to paste together S or Secs and the [n] you are using to subset the S01 columns, but R is interpreting it as you trying to take the nth item from S which does not exist. It's hard to fix without seeing your data, but you could try replacing every place you try and do this trick with something like:
pre[n][[paste("S", n, sep="")]]
Related
I have a function (col_grob) that calls another function (pal_bar) with a tilde-notation expression as follows:
## plots a colour bar with specified colour intervals
pal_bar <- function(cols) {
cols <- colorRampPalette(cols)(200)
par(mar = c(0, 0, 0, 0))
plot(1:200, rep(1, 200), col = cols, pch = 15, cex = 1.1, bty = 'n', xaxt = 'n', xlab = '', yaxt = 'n', ylab = '', main="")
}
## calls pal_bar function to plot the bar as a grob, tilde expression
col_grob <- function(pal) {
g <- ggplotify::as.grob(~pal_bar(pal))
grid::grid.draw(g)
}
I am returned the error "object 'pal' not found" when I run:
col_grob(pal = c("red", "blue"))
I came across resources and similar questions but I am not able to solve the issue with my lack of understanding of the evaluation rules. I tried ~pal_bar(I(pal)), bquote() function, and possibly structure(list(), *) but do not have sufficient knowledge of each to format the syntax correctly.
How would I get col_grob(pal = c("red", "blue")) to plot the desired colour bar for me?
A possible solution:
col_grob <- function(pal) {
txt <- substitute(pal_bar(pal))
g <- ggplotify::as.grob(as.expression(txt))
grid::grid.draw(g)
}
col_grob(pal = c("red", "blue"))
I've encountered an issue when using the pcr function in qualityTools to plot the process capabilities
install.packages("qualityTools")
library(qualityTools)
x = rweibull(1000, 2, 8) + 1000
pcr(x, "weibull", lsl = 100, usl = 117)
The histogram background is covered with numbers! Not sure what went wrong. Can somebody please take a look?
Thanks!
You can fix this by calling pcr with the argument xlab = "", i.e.
pcr(x, "weibull", lsl = 100, usl = 117, xlab = "")
Explanation. An inspection of pcr shows that it is calling hist using do.call in the following way:
do.call(hist, c(list(x[, 1], freq = FALSE, xlim = xlim, ylim = ylim, main = ""), parList))
This construct creates a name for the input that concatenates all the values of the vector. This name is then displayed as the x-axis label. You can replicate this behavior by calling, e.g.
do.call(hist, c(list(rnorm(3), main = "")))
The solution is to set xlab = "".
I have the following script:
FGM = function (n,r,z){
x = r*sqrt(n)/(2*z)
Px = 1-pnorm(x)
}
re = 10000
data = data.frame(abs(rnorm(re,0,1)), abs(rnorm(re,0,1)), abs(rnorm(re,0,1)))
colnames(data) = c("n","r","z")
data$Px = FGM(data$n,data$r,data$z)
data$x = data$r*sqrt(data$n)/(2*data$z)
par(mar=c(4.5,4.5,1,1))
plot(data$x,data$Px, xlim = c(0,3), pch = 19, cex = 0.1, xaxs="i", yaxs="i",
xlab = expression(paste("Standardized mutational size (",italic(x), ")")),
ylab = expression(paste("P"[a],"(",italic(x),")")))
Which is a recreation of the graph found here (box 2). You can see in this script that I do this by just plotting 10000 small black points with various values of n,z, and r. This seems like an ugly work around, I think I should just be able to give R my function
FGM = function (n,r,z){
x = r*sqrt(n)/(2*z)
Px = 1-pnorm(x)
}
and have it plot a line on a graph. However, a few hours of scouring the web has been unproductive, and I tried a few ways with abline and lines but nothing worked, is there a way of doing it with these functions or another function?
Tried this...
plot(data$x,data$Px, xlim = c(0,3), ylim = c(0,0.5), xaxs="i", yaxs="i",
xlab = expression(paste("Standardized mutational size (",italic(x), ")")),
ylab = expression(paste("P"[a],"(",italic(x),")")), type = "n")
curve(1-pnorm(r*sqrt(n)/(2*z)), add=T)
>Error in curve(1 - pnorm(r * sqrt(n)/(2 * z)), add = T) :
'expr' must be a function, or a call or an expression containing 'x'
>
#PaulRegular offered this solution but it still plots based on data, not the formula itself. I'm looking for a solution which can produce the curve properly without large values of "re" - using the following but with "re" set to 10 you can see what I mean...
data <- data[order(data$x),]
lines(data$x, data$Px, lwd=1)
You can pass a function of just one variable to plot. I guess that you are looking for:
plot(function(x) 1-pnorm(x),0,3)
Try sorting your data by x, then add the line:
data <- data[order(data$x),]
lines(data$x, data$Px, lwd=2)
I am working on a bit of code that creates a plot consisting of multiple individual graphs, one per ID, showing longitudinal data. For visual purposes, I am limiting the number of graphs to 20 per plot using par, but there are more than 20 IDs in the dataset, and therefore I need multiple plots.
Current problem: how to avoid overwriting an earlier plot with a new plot once the code moves beyond the 20th (or N*20th) ID. I think I need to use plot.new(), but not clear how to work this in, and could not find previous post that exactly addressed this.
My code:
# Create sample data by sampling
Start <- as.Date("2012-01-01")
End <- as.Date("2013-01-01")
data1 <- data.frame(ID = sort(rep(seq(64),3)), VisitDate = sort((Start + sample.int(End-Start, 192))), Count = rnorm(192, mean = 300, sd = 12), Treat = sample(0:1, 192, replace = TRUE))
# calculate days elapsed since start date, by ID
data1$VisitDate <- with(data1,as.Date(VisitDate,format="%y-%b-%d"))
data1$Days <- unlist(with(data1,tapply(VisitDate,ID,function(x){x-x[1]})))
#Define plot function
plot_one <- function(d){
with(d, plot(Days, Count, t="n", tck=1, main=unique(d$ID), cex.main = 0.8, ylab = "", yaxt = 'n', xlab = "", xaxt="n", xlim=c(0,8), ylim=c(0,500))) # set limits
grid(lwd = 0.3, lty = 7)
with(d[d$Treat == 0,], points(Days, Count, col = 1))
with(d[d$Treat == 1,], points(Days, Count, col = 2))
}
#Create multiple plot figure
par(mfrow=c(4,5), oma = c(0.5,0.5,0.5,0.5), mar = c(0.5,0.5,0.5,0.5))
plyr::d_ply(data1, "ID", plot_one)
If you are using windows, you call windows(). If you are using a Mac, you call quartz(). These will open a new device so that your next call to (e.g.) plot() will not overwrite your existing plots.
What is the best way to implement a generic plot method, given that i have 2 series + legends?
The problem is that i want to provide some nice defaults for the colors and legends, but the user should be free to change it:
obj = list(y1 = runif(100, 0, 10), y2 = runif(100, 20, 30))
class(obj) = 'foo'
plot.foo = function(myobj, col1 = 'red', col2 = 'blue', type = 'l', ...)
{
ylim = c(min(obj$y1, obj$y2), max(obj$y1, obj$y2))
plot(myobj$y1, type = type, col = col1, panel.first = grid(col = '#A9A9A9'), ylim = ylim, ...)
lines(myobj$y2, col = col2, type = type, ...)
}
plot(obj)
This looks good, but if i call
plot(obj, col = 'black')
It raises an error:
Error in plot.foo(obj, col = "black") :
argument 2 matches multiple formal arguments
Is there a way i can handle the 2 series + legends without breaking the plot protocol?
(another problem is to synch the legend lwd and pch parameters)
And will CRAN reject my package if i get ride of the ... arg?
Thanks!
You could have a vector expected called cols with no default. You can then add:
if(missing(cols)){
col1= "red"
col2 = "black"
} else {
col1=cols[1]
col2=cols[2]
}
There are surely better ways to do it but just thought I would throw this up.