Большинство первых аргументов функций слоя ggplot2
зарезервированы для аргумента mapping
, который взят из aes
. Таким образом, в определении вашей функции у вас есть данные dataframe, неявно назначаемые переменной mapping
. Чтобы обойти это, явно назначьте data = data
в определениях вашей функции.
например
output <- ggplot() +
geom_bar(data = data, mapping = mapping,
stat="identity",
position='stack')
}
РЕДАКТИРОВАТЬ:
Есть много способов сделать это, и это действительно зависит от того, насколько сложной вы хотите, чтобы ваша функция была. Если вы собираетесь придерживаться глобального сопоставления aestheti c, то вы можете оставить сопоставление в главном вызове ggplot и назначить data = NULL
, а затем указать, какой кадр данных будет связан с каким уровнем. Рассмотрим следующий воспроизводимый пример
library(ggplot2)
data1 <- data.frame(v1=rnorm(10, 50, 20), v2=rnorm(10,30,5))
data2 <- data.frame(v1=rnorm(10, 100, 20), v2=rnorm(10,50,10))
plot_custom_ggplot <- function(df1, df2, mapping) {
ggplot(data = NULL, mapping = mapping) +
geom_point(data = df1, color = "blue") +
geom_line(data = df2, color = "red")
}
plot_custom_ggplot(data1,data2, aes(x = v1,y = v2))
В этом примере переменная отображения для каждой из функций слоя geom_*
оставлена пустой, и вместо этого отображение наследуется от основного вызова ggplot
.
Обычно каждая функция уровня знает, какие данные использовать, потому что обычно они наследуются в основной функции ggplot
. Всякий раз, когда вы указываете аргумент data
или mapping
, вы обычно переопределяете унаследованные значения. Любые пропущенные обязательные aes
сопоставления пытаются найти в основном вызове.
library(ggplot2)
data1 <- data.frame(v1=rnorm(10, 50, 20), v2=rnorm(10,30,5))
data2 <- data.frame(v1=rnorm(10, 100, 20), v2=rnorm(10,50,10), z = c("A","B"))
plot_custom_ggplot <- function(df1, df2, mapping) {
ggplot(data = NULL, mapping = mapping) +
geom_point(data = df1, color = "blue") +
geom_line(data = df2, mapping = aes(color = z)) #inherits x and y mapping from main ggplot call.
}
plot_custom_ggplot(data1,data2, aes(x = v1,y = v2))
Но добавление дополнительных сопоставлений aes рискованно, если вы также указываете data
. Это потому, что ваша data
переменная не всегда может содержать правильные столбцы.
plot_custom_ggplot(df1 = data2, df2 = data1, aes(x = v1, y = v2))
#Error in FUN(X[[i]], ...) : object 'z' not found
#
#the column z is not present in data1 object -
#R then looked globally for a z object and didnt find anything.
Я считаю, что рекомендуется использовать аккуратные данные при работе с ggplot, потому что все становится слишком много Полегче. Существует обычно нет причин использовать несколько фреймов данных. Особенно, если вы планируете использовать один набор отображений для всех фреймов данных. Хорошее исключение - если вы пишете функцию построения для пользовательского объекта R, в котором вы знаете, как он определен.
В противном случае рассмотрите и сравните, как эти две функции работают в этом примере:
data1 <- data.frame(v1=rnorm(20, 50, 20), v2=rnorm(20,30,5), letters= letters[1:20], id = "df1")
data2 <- data.frame(v1=rnorm(20, 100, 20), v2=rnorm(20,50,10), letters = letters[17:26], id = "df2")
set.seed(76)
plot_custom_ggplot2 <- function(df, mapping) {
ggplot(data = df, mapping = mapping) +
geom_bar(stat = "identity",
position="stack")
}
plot_custom_ggplot <- function(df1, df2, mapping) {
ggplot(data = NULL, mapping = mapping) +
geom_bar(data = df1, stat = "identity",
position="stack") +
geom_bar(data = df2, stat = "identity",
position="stack")
}
plot_custom_ggplot(data1,data2, aes(x = letters,y = v2, fill = id))
plot_custom_ggplot2(rbind(data1,data2), aes(x = letters, y = v2, fill = id))
На первом графике красные полосы для q, r, s и t скрыты за синими полосами. Это потому, что они добавляются друг на друга как layers
. На втором графике эти значения фактически складываются, потому что эти значения были добавлены вместе в один слой, а не в два отдельных.
Надеюсь, это даст вам достаточно информации для написания вашей функции ggplot.