Пример 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" для агрегирования.