如果一组中的行数超过 X 个观察值,则随机抽取 X 个行数
If the number of rows in a group exceeds X number of observations, randomly sample X number of rows
我需要减少数据集中的行数。为此,我的策略是让一组中的行数超过 X 个观察值,如果一组中的行数超过 X
行,则从每个组中随机抽取 X
行数。
假设以下数据集:
set.seed(123)
n <- 10
df <- data.frame(id = c(1:n),
group = sample(1:3, n, replace = T))
> df
id group
1 1 3
2 2 3
3 3 3
4 4 2
5 5 3
6 6 2
7 7 2
8 8 2
9 9 3
10 10 1
其中 X == 2
。让我们数一数每组中的行数。
> table(df$group)
1 2 3
1 4 5
这意味着在最终结果中,我希望在第 1 组中有 1 个观察值,在第 2 组和第 3 组中有 2 个观察值。保留在第 2 组和第 3 组中的行应该随机选择。这会将数据的大小从 10 行减少到 5 行。
如何高效地执行此操作?
谢谢!
这是一种按列分组并在slice
中创建条件以检查行数(n()
)是否大于'X'的方法,对序列进行采样具有 X
或 return row_number()
的行 (row_number()
) 的行数(或示例,以防 X
是不同的值
library(dplyr)
X <- 2
df %>%
group_by(group) %>%
slice(if(n() >= X) sample(row_number(), X, replace = FALSE) else
sample(row_number())) %>%
ungroup
-输出
# A tibble: 5 × 2
id group
<int> <int>
1 10 1
2 8 2
3 4 2
4 1 3
5 9 3
我正在使用 data.table
添加一个似乎有效的替代方法。很高兴有替代品。
library(data.table)
X <- 2
setkey(df, "id")
df[
df[,
if(.N >= X)
.I[sample(.N, X, replace = FALSE)]
else
.I[sample(.N, replace = FALSE)],
by = group
]$V1
]
这导致了这个结果。
id group
1: 5 3
2: 2 3
3: 6 2
4: 4 2
5: 10 1
当我们按组随机sample
行时,可能我们可以使用pmin
df %>%
group_by(group) %>%
slice(sample(n(), pmin(n(), 2))) %>%
ungroup()
及以下是 data.table
等价物
setDT(df)[, .SD[sample(.N, pmin(.N, X))], group]
我需要减少数据集中的行数。为此,我的策略是让一组中的行数超过 X 个观察值,如果一组中的行数超过 X
行,则从每个组中随机抽取 X
行数。
假设以下数据集:
set.seed(123)
n <- 10
df <- data.frame(id = c(1:n),
group = sample(1:3, n, replace = T))
> df
id group
1 1 3
2 2 3
3 3 3
4 4 2
5 5 3
6 6 2
7 7 2
8 8 2
9 9 3
10 10 1
其中 X == 2
。让我们数一数每组中的行数。
> table(df$group)
1 2 3
1 4 5
这意味着在最终结果中,我希望在第 1 组中有 1 个观察值,在第 2 组和第 3 组中有 2 个观察值。保留在第 2 组和第 3 组中的行应该随机选择。这会将数据的大小从 10 行减少到 5 行。
如何高效地执行此操作?
谢谢!
这是一种按列分组并在slice
中创建条件以检查行数(n()
)是否大于'X'的方法,对序列进行采样具有 X
或 return row_number()
的行 (row_number()
) 的行数(或示例,以防 X
是不同的值
library(dplyr)
X <- 2
df %>%
group_by(group) %>%
slice(if(n() >= X) sample(row_number(), X, replace = FALSE) else
sample(row_number())) %>%
ungroup
-输出
# A tibble: 5 × 2
id group
<int> <int>
1 10 1
2 8 2
3 4 2
4 1 3
5 9 3
我正在使用 data.table
添加一个似乎有效的替代方法。很高兴有替代品。
library(data.table)
X <- 2
setkey(df, "id")
df[
df[,
if(.N >= X)
.I[sample(.N, X, replace = FALSE)]
else
.I[sample(.N, replace = FALSE)],
by = group
]$V1
]
这导致了这个结果。
id group
1: 5 3
2: 2 3
3: 6 2
4: 4 2
5: 10 1
当我们按组随机sample
行时,可能我们可以使用pmin
df %>%
group_by(group) %>%
slice(sample(n(), pmin(n(), 2))) %>%
ungroup()
及以下是 data.table
等价物
setDT(df)[, .SD[sample(.N, pmin(.N, X))], group]