Rの関数を複製、編集して利用する方法

Rの関数を複製、編集して利用する方法です。

ここではサンプル関数として ggplot {ggplot2} を利用します

library(ggplot2)
methods(ggplot)
[1] ggplot.default*  ggplot.function*
see '?methods' for accessing help and source code

関数 ggplot.default を確認します。

getAnywhere(ggplot.default)
A single object matching 'ggplot.default' was found
It was found in the following places
  registered S3 method for ggplot from namespace ggplot2
  namespace:ggplot2
with value

function (data = NULL, mapping = aes(), ..., environment = parent.frame()) 
{
    if (!missing(mapping) && !inherits(mapping, "uneval")) {
        cli::cli_abort(c("{.arg mapping} must be created with {.fn aes}.", 
            x = "You've supplied {.obj_type_friendly {mapping}}."))
    }
    data <- fortify(data, ...)
    p <- structure(list(data = data, layers = list(), scales = scales_list(), 
        guides = guides_list(), mapping = mapping, theme = list(), 
        coordinates = coord_cartesian(default = TRUE), facet = facet_null(), 
        plot_env = environment, layout = ggproto(NULL, Layout)), 
        class = c("gg", "ggplot"))
    p$labels <- make_labels(mapping)
    set_last_plot(p)
    p
}
<bytecode: 0x000001bd39d75eb8>
<environment: namespace:ggplot2>

始めは単純に複製して利用してみます。

ggplot.default <-
  function(data = NULL, mapping = aes(), ..., environment = parent.frame()) {
    if (!missing(mapping) && !inherits(mapping, "uneval")) {
      cli::cli_abort(c("{.arg mapping} must be created with {.fn aes}.",
        x = "You've supplied {.obj_type_friendly {mapping}}."
      ))
    }
    data <- fortify(data, ...)
    p <- structure(
      list(
        data = data, layers = list(), scales = scales_list(),
        guides = guides_list(), mapping = mapping, theme = list(),
        coordinates = coord_cartesian(default = TRUE), facet = facet_null(),
        plot_env = environment, layout = ggproto(NULL, Layout)
      ),
      class = c("gg", "ggplot")
    )
    p$labels <- make_labels(mapping)
    set_last_plot(p)
    p
  }
ggplot(data = iris, mapping = aes(x = Sepal.Length, y = Sepal.Width, colour = Species)) +
  geom_point()
Error in scales_list(): could not find function "scales_list"

関数 scales_list が見つからない、とのエラーメッセージが表示されます。

ggplot環境(environment) を確認します。

environment(ggplot)
<environment: namespace:ggplot2>

複製した ggplot.default環境(environment) を確認します。

environment(ggplot.default)
<environment: R_GlobalEnv>

ggplot.default の環境を ggplot に合わせます。

(environment(ggplot.default) <- environment(ggplot))
<environment: namespace:ggplot2>

改めてグラフを作成します。

ggplot(data = iris, mapping = aes(x = Sepal.Length, y = Sepal.Width, colour = Species)) +
  geom_point()
Figure 1

続いて、エラーメッセージ中の mappingマッピング 変更したうえで、意図的にエラーが出るようコードを変更します。下記コード中のコメントアウト2行を確認してください。

ggplot.default <-
  function(data = NULL, mapping = aes(), ..., environment = parent.frame()) {
    # if (!missing(mapping) && !inherits(mapping, "uneval")) {
    #     cli::cli_abort(c("{.arg mapping} must be created with {.fn aes}.",
    if (!missing(mapping) || !inherits(mapping, "uneval")) {
      cli::cli_abort(c("{.arg マッピング} must be created with {.fn aes}.",
        x = "You've supplied {.obj_type_friendly {mapping}}."
      ))
    }
    data <- fortify(data, ...)
    p <- structure(
      list(
        data = data, layers = list(), scales = scales_list(),
        guides = guides_list(), mapping = mapping, theme = list(),
        coordinates = coord_cartesian(default = TRUE), facet = facet_null(),
        plot_env = environment, layout = ggproto(NULL, Layout)
      ),
      class = c("gg", "ggplot")
    )
    p$labels <- make_labels(mapping)
    set_last_plot(p)
    p
  }
environment(ggplot.default)
(environment(ggplot.default) <- environment(ggplot))
<environment: R_GlobalEnv>
<environment: namespace:ggplot2>
ggplot(data = iris, mapping = aes(x = Sepal.Length, y = Sepal.Width, colour = Species)) +
  geom_point()
Error in `ggplot()`:
! `マッピング` must be created with `aes()`.
✖ You've supplied an <uneval> object.

編集後のエラーメッセージが出力されます。

以上です。