2

编辑:我同意 Roland 的观点,即我不需要将所有文本都花在 Shiny 特定的东西上。在仔细考虑之后删除并添加了数据框应该是什么样子的要点。


EDIT_2:虽然这些shiny东西与问题并不真正相关,但如果路人有兴趣看看我在做什么,我在下面使用 Roland 的解决方案创建了一个示例。对图形加载要有耐心;它可能有点慢。


我正在尝试在 R 和shiny. 我有四个变量,我想在等高线图中显示它们的相互作用。对于每个变量,我让用户定义一个范围和一个保持值。每个变量有两种情况:

  • 用作轴变量之一:范围决定了我预测模型中该变量的新响应的值
  • 图中未直接显示:保持值用于将非特征变量设置为恒定值,以便我对其他两个变量的预测为每个变量和组合仅产生一个唯一/单个表面zxy

我遇到了以对生成等高线图网格友好的方式处理数据的问题。理想情况下,我希望有一个屏幕显示其他四个变量(4 C 2)之间的 6 个交互。

我基本上需要两组数据:

  • 一个用于训练模型的输入数据集的原始形式(这样我就可以predict(model, newData)获取要用于的输出列z值的输出列
  • 用于绘图/刻面的前一个子集/重新排列的形式

对于面向方面的版本,这就是我所需要的(在我看来;也许有更好的方法):

| x        | y        | z | col | row |
|----------+----------+---+-----+-----|
| var1_min | var2_min | z |   1 |   1 |
| var1_min | ...      | z |   1 |   1 |
| var1_min | var2_max | z |   1 |   1 |
| ...      | ...      | z |   1 |   1 |
| var1_max | var2_min | z |   1 |   1 |
| var1_max | ...      | z |   1 |   1 |
| var1_max | var2_max | z |   1 |   1 |
|----------+----------+---+-----+-----|
| var1_min | var3_min | z |   1 |   2 |
| var1_min | ...      | z |   1 |   2 |
| var1_min | var3_max | z |   1 |   2 |
| ...      | ...      | z |   1 |   2 |
| var1_max | var3_min | z |   1 |   2 |
| var1_max | ...      | z |   1 |   2 |
| var1_max | var3_max | z |   1 |   2 |
|----------+----------+---+-----+-----|
| ...      | ...      | z |     |     |
|----------+----------+---+-----+-----|
| var3_min | var4_min | z |   3 |   2 |
| var3_min | ...      | z |   3 |   2 |
| var3_min | var4_max | z |   3 |   2 |
| ...      | ...      | z |   3 |   2 |
| var3_max | var4_min | z |   3 |   2 |
| var3_max | ...      | z |   3 |   2 |
| var3_max | var4_max | z |   3 |   2 |
|----------+----------+---+-----+-----|

这样,我就有了我的xy值、来自模型的相应预测响应的列,以及创建一个facet_gridwith(2x3 或 3x2)方面的东西。

对于预测数据框,表格必须与我的初始预测数据相匹配,并且几乎就像上面的演员/宽表格版本:

| var1      | var2      | var3      | var4      |
|-----------+-----------+-----------+-----------|
| var1_min  | var2_min  | var3_hold | var4_hold |
| var1_min  | ...       | var3_hold | var4_hold |
| var1_min  | var2_max  | var3_hold | var4_hold |
| ...       | ...       | var3_hold | var4_hold |
| var1_max  | var2_min  | var3_hold | var4_hold |
| var1_max  | ...       | var3_hold | var4_hold |
| var1_max  | var2_max  | var3_hold | var4_hold |
| ...       | ...       | ...       | ...       |
| var1_hold | var2_hold | var3_max  | var4_min  |
| var1_hold | var2_hold | var3_max  | ...       |
| var1_hold | var2_hold | var3_max  | var4_max  |

z我将其输入模型以获得要在等高线图中使用的预测响应。

它也变得很棘手,因为我并不总是希望变量按自然ith顺序排列,因为我需要将它们安排为在刻面行或刻面列下具有一个共同的轴刻度(可以是其中一个,不需要两者都是)。我会安排这样的组合:

| x    | y    | row | column |
|------+------+-----+--------|
| var1 | var2 |   1 |      1 |
| var1 | var3 |   2 |      1 |
| var2 | var3 |   1 |      2 |
| var2 | var4 |   2 |      2 |
| var4 | var3 |   1 |      3 |
| var4 | var1 |   2 |      3 |

现在我可以有三列和两行分面,第 1 列有共享var1轴,第 2 列有var2,第 3 列有var4.

我想知道expand.grid手动使用六个独特的变量组合。完成后,我意识到每一行都会有两个变量设置为保持值,所以也许我可以创建这六个组合的列表,然后将非保持值变量提取到绘图数据框的两个新列中?

有什么建议么?


这是我尝试使用三个变量的一个骇人听闻的示例,试图仅关注 and 之间的var1交互c(var2, var3)

# the min/max arguments to `seq()` are like the user-defined range
# take the second argument to `c()` is to be user-defined hold value

library(ggplot2)

var1 <- seq(0, 25, length.out = 10) # hold value = 11.1
var2 <- seq(5, 45, length.out = 10) # hold value = 17
var3 <- seq(55, 90, length.out = 10) # hold value = 72

# create combinations between var1 and var2, with var3 held
test_data <- expand.grid(var1 = var1, var2 = var2, var3 = 72)

# same, but for var1 vs. var3, with var2 held
test_data <- rbind(test_data,
    expand.grid(var1 = var1, var2 = 17, var3 = var3))

# create response; analog to using predict() in real life
test_data$resp <- (test_data$var1 + test_data$var2) / test_data$var3

# facet variable placeholder and filling in
test_data$facet <- rep("", nrow(test_data))
test_data[test_data$var2 == 17, "facet"] <- "var1 vs. var3"
test_data[test_data$var3 == 72, "facet"] <- "var1 vs. var2"

# now I melted
test_data2 <- melt(test_data, id.vars = c("var1", "resp", "facet"))

不幸的是,这给我留下了一堆案例,其中value填充了来自var2and的所有保持值var3,所以我不得不删除它们:

test_data2 <- test_data2[test_data2$value != 72 & test_data2$value != 17, ]

现在,我能够做到这一点:

ggplot(test_data2, aes(x = var1, y = value, z = resp)) +
    stat_contour() + facet_grid(~ facet)

得到了我正在寻找的球场。现在我想我需要一种优雅的方式来进行组合并保持值而不会产生丑陋的结果。

在此处输入图像描述

这是一个更新的版本,现在我知道如何使用行/列在相同的轴上绘图(因为我有两列和一行,我需要两个方面的 y 轴相同,在这种情况下是var1):

ggplot(test_data2, aes(x = value, y = var1, z = resp)) + 
    stat_contour() + facet_grid(~ facet, scales = "free_x")

在此处输入图像描述

4

1 回答 1

2

我真的希望我正确地理解了你。

我创建了自己的示例,它实际上适合模型。

#some data
set.seed(42)
x1 <- rnorm(20)
x2 <- runif(20)
x3 <- rpois(20,10)
x4 <- rexp(20)
y <- 10 + 2*x1 + 3*x2^2 + 4*x3 +5*x4 + rnorm(20, sd=0.1)

dat <- data.frame(x1, x2, x3, x4, y)

#fit the model
fit <- lm(y~x1+I(x2^2)+x3+x4, data=dat)
summary(fit)

#ranges and fixed values
fix_x <- c(0.3, 0.4, 15, 1)
min_x <- c(-3, 0, 5, 0)
max_x <- c(3, 1, 20, 7)

#all combinations
combis <- combn(seq_len(ncol(dat)-1),2)
#number of x-values 
#(warning! don't make too large since expand.grid is used)
n <- 100

#create new data and predict for each combination
newdat <- lapply(seq_len(ncol(combis)),
                 function(i) {
                   gr <- expand.grid(seq(from=min_x[combis[1,i]],
                                         to=max_x[combis[1,i]],
                                         length.out=n),
                                     seq(from=min_x[combis[2,i]],
                                         to=max_x[combis[2,i]],
                                         length.out=n))

                   newdat <- as.data.frame(matrix(nrow=nrow(gr), ncol=ncol(dat)-1))
                   newdat[,combis[,i]] <- gr
                   newdat[,-combis[,i]] <- matrix(rep(fix_x[-combis[,i]],each=nrow(gr)), nrow=nrow(gr))

                   newdat <- as.data.frame(newdat)
                   names(newdat) <- head(names(dat),-1)

                   newdat$y <- predict(fit, newdata=newdat)

                   newdat$comb <- paste(combis[,i],collapse=" vs. ")
                   #rename so rbind works as needed
                   names(newdat)[combis[,i]] <- c("xa","xb")
                   names(newdat)[-combis[,i]] <- c(paste0("fix",letters[seq_len(ncol(dat)-3)]), "y", "comb")
                   newdat
                 })

newdat <- do.call(rbind,newdat)

#plot
library(ggplot2)
ggplot(newdat, aes(x=xa, y=xb, z=y)) + 
  stat_contour() + 
  facet_wrap(~comb, scales="free", ncol=2) +
  xlab("") +
  ylab("")

在此处输入图像描述

于 2013-07-31T14:39:22.103 回答