如何在 R 中模拟每组离群值的分组数据分布
How to simulate grouped data distributions with outliers per group in R
我需要在 R 中模拟一个包含 3 列的数据框。
前两列必须是两个分类变量,最后一个是连续变量。
数据框应如下所示:
col3 中的数字仅供参考。重要的是 col1(即第一个分类变量)应呈现两个可能的值(即我示例中的“A”和“B”),而 col2(即第二个分类变量)应呈现其他两个可能的值(即我的示例中的“Y”和“X”)。可以看到,这样我们可以识别出四组行:
- 第 1 列为“A”,第 2 列为“Y”的行;
- col1 中为“A”且 col2 中为“X”的行;
- col1 中为“B”且 col2 中为“Y”的行;
- 第 1 列为“B”,第 2 列为“X”的行。
我想要的是编译 col3 以便在上述四组中的每一组中都有异常值(在某种意义上,例如,第一组中的异常值不一定是包含在第二个)。
不太确定您想要 col3
的分布,但是通过将正态分布与 col1
和 col2
定义的输入一起使用,然后将它们编码为一个因子,你可以这样做:
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))
我需要在 R 中模拟一个包含 3 列的数据框。
前两列必须是两个分类变量,最后一个是连续变量。
数据框应如下所示:
col3 中的数字仅供参考。重要的是 col1(即第一个分类变量)应呈现两个可能的值(即我示例中的“A”和“B”),而 col2(即第二个分类变量)应呈现其他两个可能的值(即我的示例中的“Y”和“X”)。可以看到,这样我们可以识别出四组行:
- 第 1 列为“A”,第 2 列为“Y”的行;
- col1 中为“A”且 col2 中为“X”的行;
- col1 中为“B”且 col2 中为“Y”的行;
- 第 1 列为“B”,第 2 列为“X”的行。
我想要的是编译 col3 以便在上述四组中的每一组中都有异常值(在某种意义上,例如,第一组中的异常值不一定是包含在第二个)。
不太确定您想要 col3
的分布,但是通过将正态分布与 col1
和 col2
定义的输入一起使用,然后将它们编码为一个因子,你可以这样做:
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))