How to Set Ggplot X-Label Equal to Variable Name During Lapply

How to set ggplot x-label equal to variable name during lapply?

I modify your generate_plot a little bit and use the version of ggplot2 (> v3.0.0) which supports tidy evaluation

Explanation:

  • Inside the function, we use rlang::sym to turn a string into a symbol then unquote it inside aes using !! (bang bang)

  • To call the function, use purrr::map to loop through df column names

See more:

  • https://dplyr.tidyverse.org/articles/programming.html
  • http://rlang.r-lib.org/reference/quotation.html
library(tidyverse)

df <- data.frame(y.variable=c(11:20),
x1=c(21:30), x2=c(1:10), x3=c(31:40))

generate_plot2 <- function(df, x.variable) {
x.variable <- rlang::sym(x.variable)

ggplot(data = df, aes(!! x.variable, y.variable )) +
geom_point() +
xlab(x.variable)
}

names(df)[-1] %>%
map(~ generate_plot2(df, .x))

Sample Image

Created on 2018-04-20 by the reprex package (v0.2.0).

Key-value mapping of axis/variable labels in ggplot

I digged into the ggplot object and came up with this: the benefit is that you do not need to know the mapping in advance

library(ggplot2)

ir <- data.frame(
sp = iris$Species,
sep.len = iris$Sepal.Length,
sep.wid = iris$Sepal.Width,
pet.len = iris$Petal.Length,
pet.wid = iris$Petal.Width
)

p <- ggplot(ir, aes(x=sep.len, y=sep.wid, col=sp)) +
geom_point() +
scale_color_discrete("species")

## for lazy labels

lazy.labels <- c(
sp ='species',
sep.len='sepal length',
sep.wid='sepal width',
pet.len='petal length',
pet.wid='petal width'
)

p$labels <-lapply(p$labels,function(x){as.character(lazy.labels[x])})

Or, using a function:

plot_with_labels <- function(p, l) {
p$labels <- lapply(p$labels, function(x) { as.character(l[x]) } )
return(p)
}

plot_with_labels(p, lazy.labels)

Passing variable names in function and using them to create dynamic plot and labels in R

To make your code work use rlang::as_label(enquo(bench_country)) in geom_label instead of !!bench_country or the other options you have tried. While enquo quotes the argument rlang::as_label converts the argument or the expression to a string which can then be used as label.

With this change I get:

Sample Image

EDIT For reference here is the full code for the plotting function. I also adjusted the code to take make the title and axis label "dynamic". To avoid duplicating code I add new variable at the beginning of the function which I assign the country label as a character:

fn_create_plot_last <-
function(df, year_start, year_end, bench_country) {

bench_country_str <- rlang::as_label(enquo(bench_country))

# plotting
ggplot(df) +
geom_segment(aes(
x = benchmarked_start, xend = benchmarked_end,
y = country, yend = country,
col = continent
), alpha = 0.5, size = 7) +
geom_point(aes(x = benchmarked, y = country, col = continent), size = 9, alpha = .8) +
geom_text(aes(
x = benchmarked_start + 8, y = country,
label = paste(round(benchmarked_start))
),
col = "grey50", hjust = "right"
) +
geom_text(aes(
x = benchmarked_end - 4.0, y = country,
label = round(benchmarked_end)
),
col = "grey50", hjust = "left"
) +

# scale_x_continuous(limits = c(20,85)) +

scale_color_brewer(palette = "Pastel2") +
labs(
title = glue("Countries GdpPerCap at {year_start} & {year_end})"),
subtitle = glue("Meaning Difference of gdpPerCap of countries taken wrt {bench_country_str} \n(Benchmarked {bench_country_str} in blue line) \nFor Countries with pop > 30000000 \n(Chart created by ViSa)"),
col = "Continent",
x = glue("GdpPerCap Difference at {year_start} & {year_end} (w.r.t {bench_country_str})")
) +

# Adding benchmark line
geom_vline(xintercept = 0, col = "blue", alpha = 0.3) +
geom_label(
label = glue("{bench_country_str} - as Benchamrked line"), x = 8000, y = bench_country_str, # {bench_country}
label.padding = unit(0.35, "lines"), # Rectangle size around label
label.size = 0.15, color = "black"
) +

# background & theme settings
theme_classic() +
theme(
legend.position = "top",
axis.line = element_blank(), # axis.text = element_blank()
axis.ticks = element_blank()
) +

# Adding $ to the axis (from scales lib) <=========================
scale_x_continuous(labels = label_dollar())
}

How to use a variable to specify column name in ggplot

Note: the solution in this answer is "soft-deprecated". See the answer below using .data[[ for the currently preferred method.

You can use aes_string:

f <- function( column ) {
...
ggplot( rates.by.groups, aes_string(x="name", y="rate", colour= column,
group=column ) )
}

as long as you pass the column to the function as a string (f("majr") rather than f(majr) ). Also note that we changed the other columns, "name" and "rate", to be strings.

If for whatever reason you'd rather not use aes_string, you could change it to (the somewhat more cumbersome):

    ggplot( rates.by.groups, aes(x=name, y=rate, colour= get(column),
group=get(column) ) )

How can I loop colnames as plot titles along with data using lapply in R?

I think you just need to swap these steps:

var <- dat[,which(names(dat) == var)]
title <- var

should be

title <- var
var <- dat[,which(names(dat) == var)]

var being assigned to the column of selected data so when it is called again in title, it is looking at that vector and not the column name.

If this doesn't resole it, please give us some code to mimic the contents of data.

How do I pass variable titles into a ggplot function with lapply?

lapply() can just pass object values to a function, and its names cannot be contained.

lapply(iris, FUN = names)

$Sepal.Length $Sepal.Width $Petal.Length
NULL NULL NULL

$Petal.Width $Species
NULL NULL

You can see that every cell is NULL when I pass each column of a data frame to names(). If you want to use values and names at the same time, you need to design a bivariate function.

I take iris dataset for example:

ggBox <- function(x, name) {
ggplot(iris, aes("X", x)) + geom_boxplot() + ggtitle(name)
}

df <- iris[1:4]
name <- names(iris)[1:4]

The following 3 methods are equivalent:

mapply(FUN = ggBox, df, name, SIMPLIFY = F)

Map(f = ggBox, df, name)

purrr::map2(df, name, ggBox)


Related Topics



Leave a reply



Submit