Добавление к объекту списка в функции отображения в R

Я создаю матрицу графика рассеяния, используя GGally::ggpairs. Я использую пользовательскую функцию (под названием my_fn), чтобы создать нижние левые недиагональные подзаголовки. В процессе вызова этой настраиваемой функции есть информация о каждой из этих подсети, которая рассчитывается, и которую я хотел бы сохранить позже.

В приведенном ниже примере каждая [email protected] представляет собой структуру int [] со 100 значениями. В общей сложности он создается 10 раз в my_fn (один раз для каждого из 10 нижних левых недиагональных подзаглавов). Я пытаюсь сохранить все 10 из этих структур [email protected] в объект списка listCID.

У меня не было успеха в этом подходе, и я пробовал несколько других вариантов (например, пытаюсь поместить listCID в качестве входного параметра в my_fn или попытаться вернуть его в конце).

Возможно ли, чтобы я сохранил десять структур [email protected] через my_fn, которые будут использоваться позже? Я чувствую, что есть несколько проблем синтаксиса, которые я не совсем понимаю, что может объяснить, почему я застрял, и, кроме того, я был бы счастлив изменить название этого вопроса, если я не буду использовать соответствующую терминологию. Спасибо!

library(hexbin)
library(GGally)
library(ggplot2)

set.seed(1)

bindata <- data.frame(
    ID = paste0("ID", 1:100), 
    A = rnorm(100), B = rnorm(100), C = rnorm(100), 
    D = rnorm(100), E = rnorm(100))
    bindata$ID <- as.character(bindata$ID
)

maxVal <- max(abs(bindata[ ,2:6]))
maxRange <- c(-1 * maxVal, maxVal)

listCID <- c()

my_fn <- function(data, mapping, ...){
  x <- data[ ,c(as.character(mapping$x))]
  y <- data[ ,c(as.character(mapping$y))]
  h <- hexbin(x=x, y=y, xbins=5, shape=1, IDs=TRUE, 
              xbnds=maxRange, ybnds=maxRange)
  hexdf <- data.frame(hcell2xy(h),  [email protected], [email protected])
  listCID <- c(listCID, [email protected])
  print(listCID)
  p <- ggplot(hexdf, aes(x=x, y=y, fill=counts, hexID=hexID)) + 
            geom_hex(stat="identity")
  p
}

p <- ggpairs(bindata[ ,2:6], lower=list(continuous=my_fn))
p

введите описание изображения здесь

Ответ 1

Если я правильно понимаю вашу проблему, это довольно легко, хотя и нелегко, достигается с помощью оператора <<-.

С его помощью вы можете назначить нечто вроде глобальной переменной изнутри вашей функции.

Установите listCID <- NULL перед выполнением функции и listCID <<-c(listCID,[email protected]) внутри функции.

listCID = NULL

my_fn <- function(data, mapping, ...){
  x = data[,c(as.character(mapping$x))]
  y = data[,c(as.character(mapping$y))]
  h <- hexbin(x=x, y=y, xbins=5, shape=1, IDs=TRUE, xbnds=maxRange, ybnds=maxRange)
  hexdf <- data.frame (hcell2xy (h),  hexID = [email protected], counts = [email protected])

  if(exists("listCID")) listCID <<-c(listCID,[email protected])

  print(listCID)
  p <- ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID)) + geom_hex(stat="identity")
  p
    }

Для получения дополнительной информации о области обзора, пожалуйста, обратитесь к Hadleys excellent Advanced R: http://adv-r.had.co.nz/Environments.html

Ответ 2

В целом, не рекомендуется проверять два разных результата с помощью одной функции. В вашем случае вы хотите вернуть график и результат вычисления (идентификаторы идентификатора hexbin).

Лучше было бы рассчитать ваши результаты в шагах. Каждый шаг будет отдельной функцией. Результат первой функции (вычисление шестиугольников) можно затем использовать как вход для нескольких последующих функций (поиск идентификаторов и создание графика). Далее следует один из многих способов рефакторинга кода:

  • calc_hexbins(), в котором вы генерируете все hexbins. Эта функция может вернуть именованный список hexbins (например, список (AB = h1, AC = h2, BC = 43)). Это достигается путем перечисления всех возможных комбинаций вашего списка (A, B, C, D и E). Недостатком является то, что вы дублируете некоторую логику, которая уже находится в ggpairs().
  • gen_cids() принимает hexbins в качестве входа и генерирует все идентификаторы cID. Это простая операция, в которой вы выполняете цикл (или lappy) по всем элементам вашего списка и принимаете идентификатор cID.
  • create_plot() также принимает hexbins как вход, и это функция, в которой вы фактически генерируете график. Здесь вы можете добавить дополнительный параметр для списка hexbins (в вашем пакете GGally есть функция wrap()), чтобы сделать это). Вместо вычисления шестиугольников вы можете найти их в названном списке, который вы создали ранее, объединив A и B в строке.

Это позволяет избежать хакерских методов, таких как работа с атрибутами или использование глобальных переменных. Конечно, эти работы, но часто являются головной болью при сохранении кода. К сожалению, это также сделает ваш код немного дольше, но это может быть хорошо.