I'm plotting some functions in R. Some of them aren't continuous and I get a vertical line between the diferent curve components. I really need to get this vertical line out (It makes the function look like a no-function and I don't want that).
So, how can I do that? Right now, I'm using two vectors x andy and doing plot(x,y,type = "l") so R doesn't understand where there is a discontinuity. But I didn't find a better way.
It might not be the optimum solution, but if the number of functions is small you could split them leaving the continous parts, then just use plot for the first one and add the other with lines. e.g.:
x <- seq(1,3,1)
y <- sqrt(x)
x2 <- seq(3,6,1)
y2 <- runif(4)
plot(y ~ x, type = "l",col = 2 , ylim = c(0,2) , xlim = c(0,6))
lines(y2 ~ x2, col = 2)
Related
I am using par() function to draw a multi-panel plot and I want to add a line to exactly second plot...
par(mfrow = c(2, 2))
hist(model$residuals) # model is some predefined lm object
plot((model$residuals + model$fitted.values) ~ model$fitted.values)
# Now I want to add a line (or points or curve) to only above plot like
abline(model$coef) # but this doesn't work
qqnorm(model$residuals) # some more plots, doesn't matter which
Any help? I do not intend to use ggplot() and want to keep it simple.
The problem is not what you think to be with par; it is merely because you feed inappropriate values to abline. You changed your question several times, showing that you don't know what line should be added for different several plots. I will now clarify this, assuming mod is your fitted model.
residuals v.s. fitted
with(mod, plot(fitted.values, residuals))
abline(h = 0) ## residuals are centred, so we want a horizontal line
fitted v.s. response
with(mod, plot(fitted.values + residuals, fitted.values))
abline(0, 1) ## perfect fit has `fitted = response`, so we want line `y = x`
scatter plot with regression line
v <- attr(mod$terms, "term.labels") ## independent variable name
with(mod, plot(model[[v]], fitted.values + residuals)) ## scatter plot
abline(mod$coef) ## or simply `abline(mod)`, for add regression curve
reproducible example
set.seed(0)
xx <- rnorm(100)
yy <- 1.3 * xx - 0.2 + rnorm(100, sd = 0.5)
mod <- lm(yy ~ xx)
rm(xx, yy)
par(mfrow = c(2,2))
with(mod, plot(fitted.values, residuals))
abline(h = 0)
with(mod, plot(fitted.values + residuals, fitted.values))
abline(0, 1)
v <- attr(mod$terms, "term.labels") ## independent variable name
with(mod, plot(model[[v]], fitted.values + residuals)) ## scatter plot
abline(mod$coef) ## or simply `abline(mod)`
As #ZheyuanLi says, it's hard to see exactly what you want. Some of your problems appear to be from adding lines that don't overlap with the existing plot limits.
model <- lm(Illiteracy~Income,data.frame(state.x77))
par(mfrow = c(2, 2))
hist(model$residuals)
plot(model$residuals ~ model$fitted.values)
plot((model$residuals+model$fitted.values) ~ model$fitted.values)
Adding elements immediately after the plot works fine:
abline(a=0,b=1)
What if you want to go back and add elements to a previous frame? That's a bit difficult. Reset plot to row 1, column 2: this does not put us inside the plotting frame of the previous plot, it just gets us ready to plot in this subframe.
par(mfg=c(1,2))
We want to set up the same plot frame again: we'll cheat by plotting the same thing again (ensuring the same axis limits, etc. etc.), but turning off all aspects of the plot (new=FALSE means we don't blank out the previous plot):
plot(model$residuals ~ model$fitted.values,
type="n",new=FALSE,axes=FALSE,ann=FALSE)
abline(h=0,col=2)
Base graphics are really not designed for modifying existing plots; if you want to do much of it, you should look into the grid graphics system (which lattice and ggplot2 graphics are built on).
Let say i have a data like this
M<- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
The M has 5 columns with the same values which I want to plot it but I don't want to plot them on each other. I want to show them with a space. What I do is like below
plot(x, M[,1], ylim=range(M), ann=FALSE, axes=T,type="l")
Colm <- 2:ncol(M)
lapply(seq_along(Colm),function(i){
lines(x, M[,i], col=Colm[i])
})
Is there any way to make a distance between each line in plot ?
You can add a small change to each y value to shift each line slightly.
set.seed(595)
M <- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
plot(NA, ylim=range(M), xlim=range(x), ann=FALSE, axes=T, type="l")
# Amount by which to shift each y value
eps = seq(-0.1, 0.1, length.out=ncol(M))
lapply(1:ncol(M), function(i){
lines(x, M[,i] + eps[i], col=i)
})
UPDATE: In answer to your comment, I think the following is probably what's happening: In your sample code, x is a matrix, which behaves essentially the same as a vector when the matrix has only one column. Thus, x will return a data vector, so you can just use the object x directly in the lines function. However, if you're importing x as a data frame (for example, using x=read.table("x.txt", header=TRUE), then you need to use lines(x[,1], M[,i] + eps[i], col=i) in your code in order to get the vector of data in the first column of the data frame x.
If you use ggplot you can do this easily using the alpha command as indicated in this post:
Overlapping Lines in ggplot2
and you could also jitter the lines using code from this post..
How to jitter lines in ggplot2
I am attempting to plot discrete functions in R for a flow model equation. I have to plot the original function u(x) = tanh(x - 0.1), with u(x) on the Y-axis and x on the X-axis. I then must plot a discrete function that describes the slope.
u <- array(0,dim=c(21))
#Plot the original function u(x)=tanh(ax-x0)
curve(tanh(x-0.1), from=0, to=5, n=100, col="red", xlab="x", ylab = "u(x)")
grid (NULL,NULL, col = "lightgray", lty="dotted")
x = seq(0, 5, by=0.25)
for (i in 1:21){
u[i] = tanh(x[i]-0.1)
}
x1 = seq(0, 4.75, by=0.25)
du1 <- array(0,dim=c(20))
for (i in 1:20){
du1[i] = (u[i+1]-u[i])/0.25
}
plot(x1, du1, xlab = "x", ylab = "du/dx")
So per the definition of my derivative function, my du/dx vector will only have 20 vector points, but my x vector still has 21 points. I must then repeat giving defined du/dx vectors that have 19 and 18 vector points. Is there any way I can plot the du/dx vs. x functions all on the same graph without having to redefine x every time?
I'm not sure I'm totally clear on what you're asking, but here's code that prevents you from writing out 18 individual code blocks (using the "diff" function in base).
derivs <- matrix(NA, nrow=21, ncol=18)
x <- seq(0, 5, by=0.25)
orig <- tanh(x-0.1)
derivs[,1] <- c(diff(orig)/.25, NA)
for(col in 2:18) {
print(col)
derivs[,col] <- c((diff(derivs[,col-1])/.25), NA)
}
The resulting matrix (here called "derivs" has a column for each derivative (first column is first derivative, second is second derivative, etc...)
One reason I'm a bit confused about what you're trying for is that, if you were to plot all these on one graph, it would be a really weird graph, because the order of magnitudes are really different between the first few, and the last few derivatives.
The dimensions aren't really different for each derivative; I've simply padded it with NAs, which won't appear on a graph.
Also note that you can use the diff function to get second-order differences and so forth.
PS. The graph will probably look more reasonable if, rather than taking the differences as you did (and as I did, to emulate you), so that the different is assigned to the first x value...you probably want to center. E.g. every other derivative would actually be plotted at .125, .375, etc.)
I am plotting means of grouped data and I'm having trouble getting the legends to be right. The text is so large that one can only see the names of two groups, not all four. I have spent a long time trying to use cex-like commands to change the size, but it doesn't work. I have tried rotating them with las=3, but it doesn't work.
I cannot share the data, but the code is here:
plot.question = function(number){
#which question to plot? get ID
question = names(sorted.by.n)[number]
#the formula
form = paste0("DF.scored.g.scale ~ ",question)
#fit it to data
fit = lm(form, DF.merged.g)
#get ANOVA results
fit.anova = anova(fit)
#get ANOVA p value
p.value = round(fit.anova[[5]][2],4) #p value
#plot it
plotmeans(as.formula(form), DF.merged.g,
ylab = "4 g-items sumscore",
xlab = "Answer",
main = paste0(questions.unique[question,"text"],"\nANOVA p=",p.value),
cex.main = .8,
cex.axis = .8,
cex.lab = .8,
cex.sub = .8,
las=3,) #size of main title
}
Preferably, I'd like to simply make the text smaller, so it can fit. Alternatively, I'd like to rotate it so it can fit (perhaps along with a margin change). If not what else?
One can suppress the legends with xaxt="n", but then one has to add them some other way. Can it really not be done within the plotmeans() function?
Well I tried many things and this was the only thing that worked. Apparently plotmeans() creates a plot that you cannot modify in any way. The only thing I was able to do is to overlay text as a new only-text-plot on top of the plotmeans plot.
myfactor <- factor(rep(c('cat1','cat2','cat3'),20)) #make a factor
mynum <- runif(60) #make a numeric field
plotmeans(mynum ~ myfactor,xaxt='n') #plot them
labs <- paste(names(table(myfactor)), "") #make the names
par(new=T) #create new plot
a<-rev(as.numeric(unique(myfactor))) #count the unique factors to make a vector of their numbers to serve as the positions on the x axis
text(cex=1, x=a, y=0.2, labs, xpd=TRUE, srt=35) #insert the text on the graph.
#here you need to modify y according to your data to find the best place to plot them.
#In my case x=c(1,2,3) because I have 3 categories and y=0.2
#because this is the lowest value of the y axis. The srt argument rotates the text.
You should probably be able to either fix the y axis to have standard values and then use the minimum of that number in the y argument of the text function to make a generic function, or calculate the min value of the y axis each time.
Hope that helps!
So, I am plotting densities (histograms). For example:
d <- density(table[table$position==2,]$rt)
But, I want to plot multiple densities on the same plot. For instance, I also want to plot
density(table[table$position==3,]$rt)
density(table[table$position==4,]$rt)
density(table[table$position==5,]$rt)
Furthermore, I want to specify the center point for each of these densities.
Another way to ask this question is, how can I manually shift a density plot over by a certain number of x units? (for instance, increase all x values by 5)
As with many R analysis functions, saving the output is your friend. So is ?density.
foo<-density(something)
names(foo)
"x", "y" , "bw", "n" , "call" ,"data.name"
So,
plot(foo$x+5, foo$y, t='l')
And you're done so far as I can tell.
For the piece of your question about plotting multiple densities on the same plot, use lines:
dat <- data.frame(x = rnorm(100), y = rnorm(100) + 2, z = rnorm(100) + 5)
plot(c(-2.5,8),c(0,0.5),type = "n")
lines(density(dat$x))
lines(density(dat$y))
lines(density(dat$z))
You open an empty plotting device using plot(...,type = "n") and then draw on it using lines or points, etc.