Понимание того, как R назначает участки как объекты - PullRequest
0 голосов
/ 07 апреля 2020

Я вижу много постов, которые касаются моего вопроса, но не достигают цели. Извините, если я пропустил решения в другом месте.

Я заметил, что R, кажется, назначает разные типы графиков как разные типы объектов или как NULL, но я не уверен почему. Вы можете помочь мне распаковать это? Цель состоит в том, чтобы просто сохранить график как объект, который может быть отображен позже в различных файлах уценки, но мне не нужно ничего более сложного, чем базовая печать c - без решеток и т. Д. c.

Например,

# Toy data setup 
set.seed(63)
d <- rnorm(100)

Гистограмма Basi c не отображается при вызове одного объекта, но отображается при переносе в функцию plot ().

hist(d)       # works as expected
p1 <- hist(d) # saves as a "List of 6" with class "histogram"
p1; print(p1) # both print all data in the list but no histogram plot
plot(p1)      # shows histogram plot

Variation использование функции plot сохраняет как NULL

plot(d, type="h") # works as expected
p2 <- plot(d) # saves as "NULL (empty)"
p2; print(p2) # both print NULL as expected given how it saved
plot(p2)      # generates error message, as expected

Подход ggplot также сохраняет и работает, как и ожидалось

library(tidyverse)
ggplot() +aes(d) + geom_histogram()  # works as expected with message info
p3 <- ggplot() +aes(d) + geom_histogram()  # saves as "List of 9" with class "gg" and "ggplot"
p3  # shows histogram as expected

Таким образом, 3 различных способа показать базовую c гистограмму (как) и все ведут себя по-разному при попытке назначить сюжет как объект для последующего вызова. Даже Hist () и ggplot (), сохраненные как объекты, отображаются по-разному при вызове, даже если они оба сохраняются в виде списков.

Что мне не хватает?

Чтобы сделать вещи немного сложнее, я заметил, что если я наложу графики, как и гистограммы ниже, на один график, назначенный объект не будет содержать оба графика. Я мог бы также увидеть, что это полезно для сохранения подгоночных линий, добавленной точки или текста и т. Д. c.

Что мне нужно сделать, чтобы сохранить добавления графика к объекту графика? Следующий пример кода взят из R Блоггеров .

#Random numbers
h2<-rnorm(1000,4)
h1<-rnorm(1000,6)
# Histogram Colored (blue and red)
hist(h1, col=rgb(1,0,0,0.5),xlim=c(0,10), ylim=c(0,200), main="Overlapping Histogram", xlab="Variable")
hist(h2, col=rgb(0,0,1,0.5), add=T)

Они работают как положено. Однако, если я присоединю их к точке с запятой после присвоения первой объекту, первые изменения гистограмм пропадут, и перекрывающаяся гистограмма будет отсутствовать. Имеет смысл, чтобы перекрывающаяся гистограмма исчезла, поскольку вторая команда фактически не применяется к сохраненному объекту гистограммы, но мне интересно, как ее добавить.

1 Ответ

1 голос
/ 08 апреля 2020

Функции с побочным эффектом создания графика c могут что-то возвращать или не возвращать. Например, с пакетом ggplot2 он возвращает сложную структуру списка с достаточным количеством информации и предварительно определенными атрибутами, что либо (1) print его использование приведет к графическому объекту c ("grob"), либо (2) можно добавить больше слоев или изменить атрибуты этой структуры списка. Например,

library(ggplot2)
gg <- ggplot(mtcars, aes(mpg,disp)) + geom_point()
str(gg, max.level=1)
# List of 9
#  $ data       :'data.frame':  32 obs. of  11 variables:
#  $ layers     :List of 1
#  $ scales     :Classes 'ScalesList', 'ggproto', 'gg' <ggproto object: Class ScalesList, gg>
#     add: function
#     clone: function
#     find: function
#     get_scales: function
#     has_scale: function
#     input: function
#     n: function
#     non_position_scales: function
#     scales: list
#     super:  <ggproto object: Class ScalesList, gg> 
#  $ mapping    :List of 2
#   ..- attr(*, "class")= chr "uneval"
#  $ theme      : list()
#  $ coordinates:Classes 'CoordCartesian', 'Coord', 'ggproto', 'gg' <ggproto object: Class CoordCartesian, Coord, gg>
#     aspect: function
#     backtransform_range: function
#     clip: on
#     default: TRUE
#     distance: function
#     expand: TRUE
#     is_free: function
#     is_linear: function
#     labels: function
#     limits: list
#     modify_scales: function
#     range: function
#     render_axis_h: function
#     render_axis_v: function
#     render_bg: function
#     render_fg: function
#     setup_data: function
#     setup_layout: function
#     setup_panel_params: function
#     setup_params: function
#     transform: function
#     super:  <ggproto object: Class CoordCartesian, Coord, gg> 
#  $ facet      :Classes 'FacetNull', 'Facet', 'ggproto', 'gg' <ggproto object: Class FacetNull, Facet, gg>
#     compute_layout: function
#     draw_back: function
#     draw_front: function
#     draw_labels: function
#     draw_panels: function
#     finish_data: function
#     init_scales: function
#     map_data: function
#     params: list
#     setup_data: function
#     setup_params: function
#     shrink: TRUE
#     train_scales: function
#     vars: function
#     super:  <ggproto object: Class FacetNull, Facet, gg> 
#  $ plot_env   :<environment: R_GlobalEnv> 
#  $ labels     :List of 2
#  - attr(*, "class")= chr [1:2] "gg" "ggplot"

"Просто a list."

Non-grid graphi c функции иногда используют аналогичную стратегию. Например, hist всегда возвращает именованное list; если вы используете значение по умолчанию plot=TRUE, то он возвращает этот список невидимо , и одним из побочных эффектов является создание графика. Однако при hist(..., plot=FALSE) list возвращается видимым образом, и график не создается. Подобно ggplot2 методу S3 для print (ggplot2:::print.ggplot2 и его друзьям), существует метод S3 для hist возвращаемого объекта (класс histogram) с именем graphics:::plot.histogram, так что если вы делаете

h <- hist(mtcars$disp, plot = FALSE)
str(h)
# List of 6
#  $ breaks  : int [1:10] 50 100 150 200 250 300 350 400 450 500
#  $ counts  : int [1:9] 5 7 4 1 4 4 4 1 2
#  $ density : num [1:9] 0.003125 0.004375 0.0025 0.000625 0.0025 ...
#  $ mids    : num [1:9] 75 125 175 225 275 325 375 425 475
#  $ xname   : chr "mtcars$disp"
#  $ equidist: logi TRUE
#  - attr(*, "class")= chr "histogram"

тогда простой plot(h) будет генерировать сюжет. (Даже если вы строите график в первый раз со значением по умолчанию h <- hist(..., plot=TRUE), вы можете восстановить график позже с помощью plot(h).)

Но не все функции построения графиков или их вспомогательные функции что-то возвращают. Например, lines и points всегда возвращают NULL. Вы не можете «захватить» вывод из lines и (повторно) применить его позже.

Но, насколько я могу судить, ни одна базовая функция R не «возвращает» объект графика. grid функции могут, в частности, те, которые изменяют grobs.

Если вы хотите «сохранить» сам график (а не list или компоненты, использованные для его создания), тогда посмотрите на ?recordPlot, который может быть запущен сразу после любой базовой графической функции (включая вспомогательные функции lines, points, et c).

...