11

我正在使用创建散点图矩阵GGally::ggpairs。我正在使用自定义函数(下面称为my_fn)来创建左下角的非对角线子图。在调用该自定义函数的过程中,会计算出有关每个子图的信息,我想将其存储起来以备后用。

在下面的示例中,每个h@cID都是具有 100 个值的 int[] 结构。总共在 my_fn 中创建了 10 次(为 10 个左下角非对角线子图中的每一个创建一次)。我正在尝试将所有 10 个这些h@cID结构存储到listCID列表对象中。

这种方法我没有成功,我尝试了其他一些变体(例如尝试将listCID其作为输入参数放入my_fn,或尝试在最后返回它)。

我是否可以有效地存储十个h@cID结构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),  hexID=h@cell, counts=h@count)
  listCID <- c(listCID, h@cID)
  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

在此处输入图像描述

4

2 回答 2

5

如果我正确理解您的问题,这很容易,尽管不雅,使用<<-运算符实现。

有了它,您可以从函数范围内分配诸如全局变量之类的东西。

listCID <- NULL在执行函数之前和函数内部设置listCID <<-c(listCID,h@cID)

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 = h@cell, counts = h@count)

  if(exists("listCID")) listCID <<-c(listCID,h@cID)

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

有关范围界定的更多信息,请参阅 Hadleys 出色的 Advanced R:http ://adv-r.had.co.nz/Environments.html

于 2017-01-24T17:24:05.087 回答
0

通常,尝试使用一个函数返回两个不同的结果并不是一个好习惯。在您的情况下,您希望返回绘图和计算结果(hexbin cID)。

最好是逐步计算您的结果。每个步骤都是一个单独的功能。第一个函数(计算 hexbins)的结果可以用作多个后续函数(查找 cID 并创建绘图)的输入。接下来是重构代码的众多方法之一:

  • calc_hexbins()在其中生成所有 hexbins。这个函数可以返回一个命名的十六进制列表(例如 list(AB = h1, AC = h2, BC = 43))。这是通过枚举列表的所有可能组合(A、B、C、D 和 E)来实现的。缺点是您正在复制ggpairs()中已经存在的一些逻辑。
  • gen_cids()将 hexbins 作为输入并生成所有 cID。这是一个简单的操作,您可以循环(或 lappy)列表中的所有元素并获取 cID。
  • create_plot()还将 hexbins 作为输入,这是您实际生成绘图的函数。在这里,您可以为 hexbins 列表添加一个额外的参数(在您的包 GGally 中有一个函数wrap()来执行此操作)。您可以在之前生成的命名列表中查找它们,而不是计算 hexbin,方法是将 A 和 B 组合在一个字符串中。

这避免了使用属性或使用全局变量等 hacky 方法。这些工作当然可以,但在维护代码时常常令人头疼。不幸的是,这也会使您的代码更长一些,但这可能是件好事。

于 2017-01-30T14:22:23.233 回答