I have plotted linear functions with ggplot as follow:
ggplot(data.frame(x=c(0,320)), aes(x)) +
stat_function(fun=function(x)60.762126*x-549.98, geom="line", colour="black") +
stat_function(fun=function(x)-0.431181333*x+2.378735e+02, geom="line", colour="black")+
ylim(-600,600)
However, I want the 1st function to be plotted for x ranging from 0 to 12 and the 2nd function to be plotted for x ranging from 12 to max(x).
Does anyone know how to do it?
It's easiest to just calculate the data you need outside of the ggplot call first.
fun1 <- function(x) 60.762126 * x - 549.98
dat1 <- data.frame(x = c(0, 12), y = NA)
dat1$y <- fun1(dat1$x)
fun2 <- function(x) -0.431181333 * x + 2.378735e+02
dat2 <- data.frame(x = c(12, 320), y = NA)
dat2$y <- fun2(dat2$x)
ggplot(mapping = aes(x, y)) +
geom_line(data = dat1) +
geom_line(data = dat2)
Or you can join the data for the lines first (as suggested by #Heroka), resulting in an identical plot:
dat.com <- rbind(dat1, dat2)
dat.com$gr <- rep(1:2, c(nrow(dat1), nrow(dat2)))
ggplot(dat.com, aes(x, y, group = gr)) +
geom_line()
Related
df <- data.frame(y = rt(26, df = 5), name = letters)
p <- ggplot(df, aes(sample = y))
p + stat_qq() + stat_qq_line()
The above produced the plot as expected.
But now I need labels at each point, so:
df <- data.frame(y = rt(26, df = 5), name = letters)
p <- ggplot(df, aes(sample = y))
p + stat_qq() + stat_qq_line() + geom_text(label = letters)
But it complains that geom_text needs x and y aes.
how do I fix it?
I found out how to compute the y.
But don't know how to compute the x.
You can use ggplot_build() to get the coordinates of points in your plot. In your case these are found in data[[1]].
The default labels appear right on top of the points. Spacing is adjusted using the variable offset... seems to look good.
library(ggplot2)
df <- data.frame(y = rt(26, df = 5), name = letters)
myplot <- ggplot(df, aes(sample = y)) +
stat_qq() +
stat_qq_line()
x.pnts <- ggplot_build(myplot)$data[[1]]$x
y.pnts <- ggplot_build(myplot)$data[[1]]$y
offset <- (max(y.pnts) - min(y.pnts)) / 20
myplot +
geom_text(label = df$name,
x = x.pnts,
y = y.pnts + offset)
I'm starting to program in R and I'm getting stuck in this plot.
This is the plot I'm traying to make:
I'm able to do it with this code:
x <- seq(0, 10,1 )
y = x**2
z= x**3
plot(x, y, type="o", col="blue",xlab='x',ylab="y = x2")
lines(x,z,col="green")
I need to do it ussing ggplot, since I have to add futher formating, but I'm not finding the way to do it, I'm loking for the equivalen of the "hue" function on seaborn.
sns.catplot(x="sex", y="survived", hue="class", kind="point", data=titanic);
To use ggplot2, it is better to prepare a data frame with all the values. Furthermore, it is recommended to work with "long-format" data frame. We can then map the color to class, which is y and z in your example.
x <- seq(0, 10,1 )
y <- x**2
z <- x**3
# Load the tidyverse package, which contains ggplot2 and tidyr
library(tidyverse)
# Create example data frame
dat <- data.frame(x, y, z)
# Conver to long format
dat2 <- dat %>% gather(class, value, -x)
# Plot the data
ggplot(dat2,
# Map x to x, y to value, and color to class
aes(x = x, y = value, color = class)) +
# Add point and line
geom_point() +
geom_line() +
# Map the color as y is blue and z is green
scale_color_manual(values = c("y" = "blue", "z" = "green")) +
# Adjust the format to mimic the base R plot
theme_classic() +
theme(panel.grid = element_blank())
One way would be creating two dataframes separately
library(ggplot2)
df1 <- data.frame(x, y)
df2 <- data.frame(x, z)
ggplot(df1, aes(x, y)) +
geom_line(color = "blue") +
geom_point(color = "blue", shape = 1, size = 2) +
geom_line(data = df2, aes(x, z), color = "green") +
ylab("y = x2")
I'm analyzing a series that varies around zero. And to see where there are parts of the series with a tendency to be mostly positive or mostly negative I'm plotting a geom_smooth. I was wondering if it is possible to have the color of the smooth line be dependent on whether or not it is above or below 0. Below is some code that produces a graph much like what I am trying to create.
set.seed(5)
r <- runif(22, max = 5, min = -5)
t <- rep(-5:5,2)
df <- data.frame(r+t,1:22)
colnames(df) <- c("x1","x2")
ggplot(df, aes(x = x2, y = x1)) + geom_hline() + geom_line() + geom_smooth()
I considered calculating the smoothed values, adding them to the df and then using a scale_color_gradient, but I was wondering if there is a way to achieve this in ggplot directly.
You may use the n argument in geom_smooth to increase "number of points to evaluate smoother at" in order to create some more y values close to zero. Then use ggplot_build to grab the smoothed values from the ggplot object. These values are used in a geom_line, which is added on top of the original plot. Last we overplot the y = 0 values with the geom_hline.
# basic plot with a larger number of smoothed values
p <- ggplot(df, aes(x = x2, y = x1)) +
geom_line() +
geom_smooth(linetype = "blank", n = 10000)
# grab smoothed values
df2 <- ggplot_build(p)[[1]][[2]][ , c("x", "y")]
# add smoothed values with conditional color
p +
geom_line(data = df2, aes(x = x, y = y, color = y > 0)) +
geom_hline(yintercept = 0)
Something like this:
# loess data
res <- loess.smooth(df$x2, df$x1)
res <- data.frame(do.call(cbind, res))
res$posY <- ifelse(res$y >= 0, res$y, NA)
res$negY <- ifelse(res$y < 0, res$y, NA)
# plot
ggplot(df, aes(x = x2, y = x1)) +
geom_hline() +
geom_line() +
geom_line(data=res, aes(x = x, y = posY, col = "green")) +
geom_line(data=res, aes(x = x, y = negY, col = "red")) +
scale_color_identity()
I have three matrix and I want to plot the graph using ggplot2. I have the data below.
library(cluster)
require(ggplot2)
require(scales)
require(reshape2)
data(ruspini)
x <- as.matrix(ruspini[-1])
w <- matrix(W[4,])
df <- melt(data.frame(max_Wmk, min_Wmk, w, my_time = 1:10), id.var = 'my_time')
ggplot(df, aes(colour = variable, x = my_time, y = value)) +
geom_point(size = 3) +
geom_line() +
scale_y_continuous(labels = comma) +
theme_minimal()
I want to add the three plots into one plot using a beautiful ggplot2.
Moreover, I want to make the points with different values have different colors.
I'm not quite sure what you're after, here's a guess
Your data...
max <- c(175523.9, 33026.97, 21823.36, 12607.78, 9577.648, 9474.148, 4553.296, 3876.221, 2646.405, 2295.504)
min <- c(175523.9, 33026.97, 13098.45, 5246.146, 3251.847, 2282.869, 1695.64, 1204.969, 852.1595, 653.7845)
w <- c(175523.947, 33026.971, 21823.364, 5246.146, 3354.839, 2767.610, 2748.689, 1593.822, 1101.469, 1850.013)
Slight modification to your base plot code to make it work...
plot(1:10,max,type='b',xlab='Number',ylab='groups',col=3)
points(1:10,min,type='b', col=2)
points(1:10,w,type='b',col=1)
Is this what you meant?
If you want to reproduce this with ggplot2, you might do something like this...
# ggplot likes a long table, rather than a wide one, so reshape the data, and add the 'time' variable explicitly (ie. my_time = 1:10)
require(reshape2)
df <- melt(data.frame(max, min, w, my_time = 1:10), id.var = 'my_time')
# now plot, with some minor customisations...
require(ggplot2); require(scales)
ggplot(df, aes(colour = variable, x = my_time, y = value)) +
geom_point(size = 3) +
geom_line() +
scale_y_continuous(labels = comma) +
theme_minimal()
UPDATE after the question was edited and the example data changed, here's an edit to suit the new example data:
Here's your example data (there's scope for simplification and speed gains here, but that's another question):
library(cluster)
require(ggplot2)
require(scales)
require(reshape2)
data(ruspini)
x <- as.matrix(ruspini[-1])
wss <- NULL
W=matrix(data=NA,ncol=10,nrow=100)
for(j in 1:100){
k=10
for(i in 1: k){
wss[i]=kmeans(x,i)$tot.withinss
}
W[j,]=as.matrix(wss)
}
max_Wmk <- matrix(data=NA, nrow=1,ncol=10)
for(i in 1:10){
max_Wmk[,i]=max(W[,i],na.rm=TRUE)
}
min_Wmk <- matrix(data=NA, nrow=1,ncol=10)
for(i in 1:10){
min_Wmk[,i]=min(W[,i],na.rm=TRUE)
}
w <- matrix(W[4,])
Here's what you need to do to make the three objects into vectors so you can make the data frame as expected:
max_Wmk <- as.numeric(max_Wmk)
min_Wmk <- as.numeric(min_Wmk)
w <- as.numeric(w)
Now reshape and plot as before...
df <- melt(data.frame(max_Wmk, min_Wmk, w, my_time = 1:10), id.var = 'my_time')
ggplot(df, aes(colour = variable, x = my_time, y = value)) +
geom_point(size = 3) +
geom_line() +
scale_y_continuous(labels = comma) +
theme_minimal()
And here's the result:
I have a list with 9 different vectors inside. And I want plot them (dot-line) in one figure with different colors by their names. How to do that in R language?
Using a made up example:
# example data:
dat <- list(a=1:5,b=2:7,c=3:10)
# get plotting:
plot(unlist(dat),type="n",xlim=c(1,max(sapply(dat,length))))
mapply(lines,dat,col=seq_along(dat),lty=2)
legend("topleft",names(dat),lty=2,col=seq_along(dat))
No question would be complete without a ggplot answer.
dat <- list(a=1:5,b=2:7,c=3:10)
dat <- lapply(dat, function(x) cbind(x = seq_along(x), y = x))
list.names <- names(dat)
lns <- sapply(dat, nrow)
dat <- as.data.frame(do.call("rbind", dat))
dat$group <- rep(list.names, lns)
library(ggplot2)
ggplot(dat, aes(x = x, y = y, colour = group)) +
theme_bw() +
geom_line(linetype = "dotted")
To plot each line in a separate plot, use
ggplot(dat, aes(x = x, y = y, colour = group)) +
theme_bw() +
geom_line(linetype = "dotted") +
facet_wrap(~ group)