如何在 R 中模拟每组离群值的分组数据分布

How to simulate grouped data distributions with outliers per group in R

我需要在 R 中模拟一个包含 3 列的数据框。

前两列必须是两个分类变量,最后一个是连续变量。

数据框应如下所示:

col3 中的数字仅供参考。重要的是 col1(即第一个分类变量)应呈现两个可能的值(即我示例中的“A”和“B”),而 col2(即第二个分类变量)应呈现其他两个可能的值(即我的示例中的“Y”和“X”)。可以看到,这样我们可以识别出四组行:

  1. 第 1 列为“A”,第 2 列为“Y”的行;
  2. col1 中为“A”且 col2 中为“X”的行;
  3. col1 中为“B”且 col2 中为“Y”的行;
  4. 第 1 列为“B”,第 2 列为“X”的行。

我想要的是编译 col3 以便在上述四组中的每一组中都有异常值(在某种意义上,例如,第一组中的异常值不一定是包含在第二个)。

不太确定您想要 col3 的分布,但是通过将正态分布与 col1col2 定义的输入一起使用,然后将它们编码为一个因子,你可以这样做:

nsim <- 1000
col1 <- sample(1:2, nsim, replace = T)
col2 <- sample(26:25, nsim, replace = T)
col3 <- rnorm(nsim, col1*col2, col2/col1)

col1 <- factor(col1, labels = LETTERS[1:2])
col2 <- factor(col2, labels = LETTERS[26:25])

df <- data.frame(col1, col2, col3)
with(df, boxplot(col3~col1*col2))

如果要指定每次分配(如果数量不多),也可以使用ifelse函数:

nsim <- 1000
col1 <- sample(LETTERS[1:2], nsim, replace = T)
col2 <- sample(LETTERS[26:25], nsim, replace = T)
df <- data.frame(col1, col2)
df$col3 <- apply(df, 1, function(y) ifelse(y[1] == "A", ifelse(y[2]  == "Z", rnorm(1, 10, 2), rnorm(1, 11, 2)),
                                                        ifelse(y[2]  == "Z", rnorm(1, 15, 2), rnorm(1, 19, 2))))
with(df, boxplot(col3~col1*col2))

我会设置一个函数(下面的 generateDataset)来单独生成您需要的 4 个数据集。然后您可以将它们加入到一起以获得完整的 table.

我在函数参数中包含了 nOutlier 和 scaleValue 参数。这些允许您在原本正常的数据中插入异常值。

      library(tidyverse)
      
      generateDataset <- function(col1Val, col2Val, meanVal, sdVal, nVal, nOutliers, scaleValue){
        x <- data.frame(
          col1 = rep(col1Val, 10),
          col2 = rep(col2Val, 10),
          col3 = rnorm(mean = meanVal, sd = sdVal, n=nVal)
        )
        
        y <- x %>%
          sample_n(size = nOutliers) %>%
          mutate(col3New = col3 * scaleValue)
        
        z <- x %>% 
          anti_join(y, by=c("col1","col2","col3")) %>%
          bind_rows(y %>% mutate(col3 = col3New) %>% select(-col3New))
        
        return(z)
      }
      
      df <- generateDataset("A", "X", 10, 1, 200, 5, 2) %>%
        bind_rows(generateDataset("A", "Y", 10, 4, 200, 1, 10)) %>%
        bind_rows(generateDataset("B", "X", 20, 2, 200, 10, 15))
      
      ggplot(df) +
        geom_boxplot(aes(x=col1, y=col3, colour=col2))