Я пытаюсь создать оболочку ggplot2, которая регулирует масштаб по оси y в зависимости от масштаба y.
Любая идея, что вызывает эту проблему? Может есть другой подход к этой проблеме?
Я надеюсь, что пример поможет понять мою проблему. Заранее спасибо!
# setup -------------------------------------------------------------------
library(ggplot2)
df <- data.frame(
childs = c(3, 0, 2, 4, 2, 2, 2, 3, 3, 4, 5, 4, 3, 5, 7, 2, 6, 5, 0, 2),
agegrp = as.factor(c("Age 45-55",
"Age 55-65","Age 65+","Age 35-45","Age 45-55","Age 45-55",
"Age 45-55","Age 18-35","Age 35-45","Age 65+",
"Age 18-35","Age 65+","Age 18-35","Age 55-65",
"Age 65+","Age 18-35","Age 55-65","Age 55-65",
"Age 18-35","Age 35-45")),
religion = as.factor(c("None","None",
"Catholic","Catholic","None","None","None","Catholic",
"Protestant","None","Protestant","Protestant",
"Catholic","Protestant","Catholic","Other",
"Protestant","Protestant","None","Protestant"))
)
# function ----------------------------------------------------------------
plot_1 <- function(data, x, y, fill) {
plot <-
ggplot(data = data,
mapping = aes(x = {{ x }}, y = {{ y }}, fill = {{ fill }})) +
geom_col(position = "dodge")
if (is.numeric(y)) {
scale <-
scale_y_continuous(expand = expansion(mult = c(0, 0.05)),
breaks = scales::breaks_extended(),
labels = scales::label_number(big.mark = "'"))
} else {
scale <-
scale_y_discrete(expand = expansion(mult = c(0, 0.05)),
breaks = scales::breaks_extended(),
labels = scales::label_number(big.mark = "'"))
}
plot +
scale +
cowplot::theme_minimal_hgrid()
}
plot_2 <- function(data, x, y, fill) {
plot <-
ggplot(data = data,
mapping = aes(x = {{ x }}, y = {{ y }}, fill = {{ fill }})) +
geom_col(position = "dodge")
cond <- enquo(y) # tidyeval
if (is.numeric(cond)) {
scale <-
scale_y_continuous(expand = expansion(mult = c(0, 0.05)),
breaks = scales::breaks_extended(),
labels = scales::label_number(big.mark = "'"))
} else {
scale <-
scale_y_discrete(expand = expansion(mult = c(0, 0.05)),
breaks = scales::breaks_extended(),
labels = scales::label_number(big.mark = "'"))
}
plot +
scale +
cowplot::theme_minimal_hgrid()
}
plot_3 <- function(data, x, y, fill) {
plot <-
ggplot(data = data,
mapping = aes(x = {{ x }}, y = {{ y }}, fill = {{ fill }})) +
geom_col(position = "dodge")
plot +
cowplot::theme_minimal_hgrid()
}
# test --------------------------------------------------------------------
plot_1(df, agegrp, childs, religion)
#> Error in plot_1(df, agegrp, childs, religion): object 'childs' not found
plot_2(df, agegrp, childs, religion)
plot_3(df, agegrp, childs, religion)
Created on 2022-10-14 by the reprex package (v2.0.1)
@LionelHenry ошибка возникает в строке if (is.numeric(y))
, где y
явно не распознается без применения маски данных. Вместо этого я предложил if (is.numeric(data[[deparse(substitute(y))]]))
, но я думаю, что if (is.numeric(eval_tidy(enquo(y), data = data)))
больше похож на аккуратную вселенную. Я также думаю, что вы знаете более аккуратный способ выразить это?
@LionelHenry спасибо за вашу идею. к сожалению, это выдает ту же ошибку. Решение Allans работает.
Существует также более интуитивно понятный способ для пользователей tidyverse: cond <- pull(data, {{ y }})
if (is.numeric(cond))
дополнительная информация
Рад, что вы нашли решение своей проблемы, извините, у меня не было времени, чтобы проиллюстрировать мою.
Ошибка возникает внутри if (is.numeric(y))
, так как переменная y
не существует в этом контексте, где маска данных не применяется. Если вы измените его на
if (is.numeric(data[[deparse(substitute(y))]])) {
Тогда ваша функция работает, в результате чего
plot_1(df, agegrp, childs, religion)
Я думал if (is.numeric(y))
это проблема. Но я не знал, как это решить. if (is.numeric(eval_tidy(substitute(y), data = data)))
У меня работает нормально. Также спасибо за объяснение.
Я бы использовал rlang::as_name()
вместо deparse()
, потому что последний может возвращать многострочный вектор с некоторыми выражениями. Первый безопаснее и не работает, если предоставленное выражение не является символом.
@LionelHenry спасибо - я думал, ты знаешь более аккуратный способ.
Попробуйте передать
y
вdplyr::mutate()
с новым уникальным именем столбца, например.mutate(.my_y = {{ y }})
. Затем вы можете проверитьdata$.my_y
и передать его в ggplot2.