Is there a way to modify the plot coordinates using coord_cartesian() in a way that is dynamic based on the data in the ggplot call?
For example:
ggplot(cars, aes(x = speed, y = dist)) +
geom_point() +
coord_cartesian(xlim = c(min(.$speed), max(.$speed) + 10))
This doesn't work, nor does using .data$speed.
You can use the magrittr and dplyr pipe operator (%>%) to pass data into the ggplot call.
cars %>%
{ggplot(., aes(speed, dist)) +
geom_point() +
coord_cartesian(xlim = c(min(.$speed), max(.$speed) + 10))
}
Note that now you need to explicitly identify the data argument at the beginning of the ggplot call using the . pronoun.
It's a bit hacky but you can add a blank geom and add 10 to the y in the aesthetics.
ggplot(cars, aes(x = speed, y = dist)) +
geom_point() +
geom_blank(aes(y = dist + 10))
Related
Consider the following (nonsensical, but working) plot:
ggplot(mtcars,
aes(x = as.factor(cyl), y = hp)) +
geom_boxplot() +
facet_wrap( ~ am) +
geom_text(label = "test")
I'd like to pass the value of am within each facet to the label argument of geom_text. So all the labels within the left facet would read "0", all the labels within the right facet would read "1".
How could I achieve this? Simply passing am doesn't work, and neither does .$am.
Sure, just provide the label inside mapping, like this:
... +
geom_text(aes(label = am))
You could pass it as a vector like this:
library(ggplot2)
ggplot(mtcars, aes(x = as.factor(cyl), y = hp)) +
geom_boxplot() +
facet_wrap( ~ am) +
geom_text(label = mtcars$am)
Created on 2022-11-03 with reprex v2.0.2
I am trying to create a barplot with the ggplot2 library. My data is stored in read.csv2 format.
# Library
library(ggplot2)
library(tidyverse) # function "%>%"
# 1. Read data (comma separated)
data = read.csv2(text = "Age;Frequency
0 - 10;1
11 - 20;5
21 - 30;20
31 - 40;13
41 - 49;1")
# 2. Print table
df <- as.data.frame(data)
df
# 3. Plot bar chart
ggplot(df, aes(x = Age)) +
geom_bar() +
theme_classic()
The code runs fine, but it produces a graph that looks like all data are at max all the time.
You need to specify your y axis as well:
ggplot(df, aes(x = Age, y = Frequency)) +
geom_bar(stat = "identity") +
theme_classic()
The default value of geom_bar plots the frequency of the values which is 1 for all the Age values here (Check table(df$Age)). You may use geom_bar with stat = 'identity'
library(ggplot2)
ggplot(df, aes(Age, Frequency)) +
geom_bar(stat = 'identity') +
theme_classic()
OR geom_col :
ggplot(df, aes(Age, Frequency)) +
geom_col() +
theme_classic()
Is there an easy way to scale a ggplot by log base 20 or higher? This works great:
ggplot(data, aes(x, y)) + geom_line() + scale_x_log10()
Unfortunately base 10 too small. There's a more general scale_x_continuous function that takes a trans argument, but there doesn't appear to be any log transforms higher than base 10.
Here's a worked example of creating a new trans object to use in your plot:
Initial plot
library(ggplot2)
df <- data.frame(x = 1:10, y = 10^(1:10))
p <- ggplot(df, aes(x, y)) + geom_line()
p
With log scale using base 100
p + scale_y_continuous(trans = scales::trans_new(name = "log100",
transform = function(x) log(x, 100),
inverse = function(x) 100^x,
domain = c(1e-16, Inf)),
breaks = scales::breaks_log(5, 100),
labels = scales::comma)
Created on 2020-12-07 by the reprex package (v0.3.0)
The scales package provides transforms to the scale_x_continuous() function. You can either use the built-in flexible log transform or create your own using the trans_new() function.
Built-in with base-20:
require(scales)
base=20
p1 <- ggplot(mpg, aes(displ, hwy)) +
geom_point()
p1 + scale_y_continuous(trans = scales::log_trans(base))
Make your own transform:
require(scales)
logTrans <- function(base=20){
trans_new(name='logT',
transform=function(y){
return(log(y, base=base))
},
inverse=function(y){
return(base^y)
})
}
base=20
p1 + scale_y_p1 <- ggplot(mpg, aes(displ, hwy)) +
geom_point()
p1 + continuous(trans = logTrans(base=base))
In my ggplot below, I'm trying to change the 10 facet labels of facet_wrap using labeller(sch.id=paste0("sch.id:", unique(ten$sch.id))).
However, the plot shows NA instead of the correct facet labels, I wonder what the fix is?
library(ggplot2)
hsb <- read.csv('https://raw.githubusercontent.com/rnorouzian/e/master/hsb.csv')
ten <- subset(hsb, sch.id %in% unique(sch.id)[1:10])
p <- ten %>% ggplot() + aes(ses, math) + geom_point() +
facet_wrap(~sch.id) + geom_smooth(method = "lm", se = FALSE)
p + facet_wrap(~sch.id, labeller = labeller(sch.id=paste0("sch.id:", unique(ten$sch.id)))) ## HERE ##
The problem seems to be that you are passing a variable to the labeller function but facet_wrap already passes its own faceting variable. A conflict occurs and the result are NA's.
The solution is to create a labeller function as a function of a variable x (or any other name as long as it's not the faceting variables' names) and then coerce to labeller with as_labeller.
Note that there is no need for unique, just like there is no need for it in the facet_wrap formula.
p <- ten %>% ggplot() + aes(ses, math) + geom_point() +
geom_smooth(method = "lm", formula = y ~ x, se = FALSE)
cust_labeller <- function(x) paste0("sch.id:", x)
p + facet_wrap(~ sch.id,
labeller = as_labeller(cust_labeller)) ## HERE ##
I think the easiest way would be to change sch.id before plotting.
library(ggplot2)
ten$sch.id <- paste0("sch.id:", ten$sch.id)
ggplot(ten) + aes(ses, math) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~sch.id)
If you don't want to modify your data and want to use the labeller argument you can create a named vector and use it in labeller.
cust_label <- setNames(paste0("sch.id:", unique(ten$sch.id)), unique(ten$sch.id))
ggplot(ten) + aes(ses, math) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~sch.id, labeller = as_labeller(cust_label))
I get an error when i try to use more than one dataframe in a ggplot2; Error: mapping must be created by aes()
xdf <- data.frame(x=1:3, y=c(18,11,16))
ydf <- data.frame(x=c(5,7), y=c(18,11))
ggplot(xdf, aes(x,y))+
geom_point()+
geom_point(ydf, aes(x,y) )
Is this solvable...?
You need to specify that ydf is the data parameter:
ggplot(xdf, aes(x,y))+
geom_point()+
geom_point(data=ydf, aes(x,y))
Some additional remarks for others who need to work with different data in ggplot2:
If you define aes globally within the function ggplot and you need the same aesthetics, you do not have to write them again.
ggplot(xdf, aes(x, y)) +
geom_point() +
geom_point(data = ydf)
If you need different aesthetics, you can set inherit.aes = FALSE to ignore the global aesthetics.
ggplot(xdf, aes(x, y, color = z)) +
geom_point() +
geom_point(data=ydf, aes(y, x), inherit.aes = FALSE)