Пример n случайных строк для каждой группы в кадре данных
Из этих вопросов - Случайная выборка строк из подмножества кадра данных R и Примеры случайных строк в dataframe Я легко вижу, как случайным образом выбирать (выбирать) "n" строки из строк df или "n", которые исходят из определенного уровня фактора в пределах df.
Вот несколько примеров данных:
df <- data.frame(matrix(rnorm(80), nrow=40))
df$color <- rep(c("blue", "red", "yellow", "pink"), each=10)
df[sample(nrow(df), 3), ] #samples 3 random rows from df, without replacement.
К примеру. просто выберите 3 случайных строки из "розового" цвета - используя library(kimisc)
:
library(kimisc)
sample.rows(subset(df, color == "pink"), 3)
или написать пользовательскую функцию:
sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
sample.df(subset(df, color == "pink"), 3)
Тем не менее, я хочу пробовать 3 (или n) случайные строки с каждого уровня фактора. То есть новый df будет иметь 12 строк (3 от синего, 3 от красного, 3 от желтого, 3 от розового). Очевидно, что можно запускать это несколько раз, создавать newdfs для каждого цвета, а затем связывать их вместе, но я ищу более простое решение.
Ответы
Ответ 1
Вы можете назначить случайный идентификатор для каждого элемента с определенным уровнем фактора с помощью ave
. Затем вы можете выбрать все случайные идентификаторы в определенном диапазоне.
rndid <- with(df, ave(X1, color, FUN=function(x) {sample.int(length(x))}))
df[rndid<=3,]
Это имеет то преимущество, что вы сохраняете исходный порядок строк и имена строк, если это то, что вас интересует. Кроме того, вы можете повторно использовать вектор rndid
для создания подмножества разной длины довольно легко.
Ответ 2
В версиях dplyr
0.3 и более поздних версиях это работает отлично:
df %>% group_by(color) %>% sample_n(size = 3)
Старые версии dplyr
(версия <= 0,2)
Я решил ответить на это с помощью dplyr, считая, что это сработает:
df %.% group_by(color) %.% sample_n(size = 3)
Но оказывается, что в 0.2 существует метод sample_n.grouped_df
S3, но он не зарегистрирован в файле NAMESPACE, поэтому он никогда не отправляется. Вместо этого я должен был сделать это:
df %.% group_by(color) %.% dplyr:::sample_n.grouped_df(size = 3)
Source: local data frame [12 x 3]
Groups: color
X1 X2 color
8 0.66152710 -0.7767473 blue
1 -0.70293752 -0.2372700 blue
2 -0.46691793 -0.4382669 blue
32 -0.47547565 -1.0179842 pink
31 -0.15254540 -0.6149726 pink
39 0.08135292 -0.2141423 pink
15 0.47721644 -1.5033192 red
16 1.26160230 1.1202527 red
12 -2.18431919 0.2370912 red
24 0.10493757 1.4065835 yellow
21 -0.03950873 -1.1582658 yellow
28 -2.15872261 -1.5499822 yellow
Предположительно это будет исправлено в будущем обновлении.
Ответ 3
Я бы рассмотрел my stratified
функцию, которая в настоящее время размещается как GitHub Gist.
Получить его с помощью
library(devtools) ## To download "stratified"
source_gist("https://gist.github.com/mrdwab/6424112")
И используйте его с помощью:
stratified(df, "color", 3)
Существует несколько различных функций, которые удобны для стратифицированной выборки. Например, вы также можете взять образец "на лету".
stratified(df, "color", 3, select = list(color = c("blue", "red")))
Чтобы дать вам представление о том, что делает функция, здесь приведены аргументы stratified
:
-
df
: вход data.frame
-
group
: вектор символов столбца или столбцов, составляющих "страты".
-
size
: желаемый размер выборки.
- Если
size
- значение меньше 1, из каждой страты берется пропорциональная выборка.
- Если
size
- одно целое число от 1 или более, это число выборок берется из каждого слоя.
- Если
size
- вектор целых чисел, указанное количество выборок берется для каждого страта. Рекомендуется использовать именованный вектор. Например, если у вас есть две страты, "A" и "B" , и вам нужно 5 образцов из "A" и 10 из "B" , вы должны ввести size = c(A = 5, B = 10)
.
-
select
: Это позволяет вам подмножать группы в процессе выборки. Это list
. Например, если ваша переменная group
была "Группой", и она содержала три страты: "A", "B" и "C", но вы хотели только попробовать с "A" и "C", вы можете используйте select = list(Group = c("A", "C"))
.
-
replace
: для выборки с заменой.
Ответ 4
Здесь решение. Разобьем data.frame на цветовые группы. Затем мы выбираем 3 строки из каждой группы. Это дает список data.frames.
df2 <- lapply(split(df, df$color),
function(subdf) subdf[sample(1:nrow(subdf), 3),]
)
Чтобы получить желаемый результат, мы объединяем список data.frames в 1 data.frame:
do.call('rbind', df2)
## X1 X2 color
## blue.3 -1.22677188 1.25648082 blue
## blue.4 -0.54516686 -1.94342967 blue
## blue.1 0.44647071 0.16283326 blue
## pink.40 0.23520296 -0.40411906 pink
## pink.34 0.02033939 -0.32321309 pink
## pink.33 -1.01790533 -1.22618575 pink
## red.16 1.86545895 1.11691250 red
## red.11 1.35748078 -0.36044728 red
## red.13 -0.02425645 0.85335279 red
## yellow.21 1.96728782 -1.81388110 yellow
## yellow.25 -0.48084967 0.07865186 yellow
## yellow.24 -0.07056236 -0.28514125 yellow
Ответ 5
Вот базовый способ, который допускает несколько групп и выборку с заменой:
n <- 3
resample <- TRUE
index <- 1:nrow(df)
fun <- function(x) sample(x, n, replace = resample)
a <- aggregate(index, by = list(group = df$color), FUN = fun )
df[c(a$x),]
Чтобы добавить другую группу, включите ее в аргумент "by" для агрегирования.