Случайная выборка строк из подмножества R-кадра
Есть ли хороший способ получить образец строк из части фрейма данных?
Если у меня есть только такие данные, как
gender <- c("F", "M", "M", "F", "F", "M", "F", "F")
age <- c(23, 25, 27, 29, 31, 33, 35, 37)
то я могу легко пробовать возрасты трех из Fs с
sample(age[gender == "F"], 3)
и получить что-то вроде
[1] 31 35 29
но если я верну эти данные в фрейм данных
mydf <- data.frame(gender, age)
Я не могу использовать очевидные
sample(mydf[mydf$gender == "F", ], 3)
хотя я могу придумать что-то свернутое с абсурдным числом скобок вроде
mydf[sample((1:nrow(mydf))[mydf$gender == "F"], 3), ]
и получить то, что я хочу, что-то вроде
gender age
7 F 35
4 F 29
1 F 23
Есть ли лучший способ, который заставляет меня меньше времени на то, чтобы написать, как писать?
Ответы
Ответ 1
Ваш сложный путь в значительной степени, как это сделать - я думаю, что все ответы будут вариациями этой темы.
Например, мне нравится сначала генерировать индексы mydf$gender=="F"
:
idx <- which(mydf$gender=="F")
Затем я беру пример из этого:
mydf[ sample(idx,3), ]
Итак, в одной строке (хотя вы уменьшаете абсурдное количество скобок и, возможно, упрощаете код, имея несколько строк):
mydf[ sample( which(mydf$gender=='F'), 3 ), ]
Пока "wheee я хакер!" часть меня предпочитает однострочный, разумная часть меня говорит, что, хотя двухстрочный слой - две строки, это гораздо более понятно - это только ваш выбор.
Ответ 2
Вы говорите, что я не могу использовать очевидное:
sample(mydf[mydf$gender == "F", ], 3)
но вы можете написать свою собственную функцию для этого:
sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
затем запустите его при выборе подмножества:
sample.df(mydf[mydf$gender == "F", ], 3)
# gender age
# 5 F 31
# 4 F 29
# 1 F 23
(Лично я считаю, что sample.df(subset(mydf, gender == "F"), 3)
легче читать.)
Ответ 3
Теперь это проще с расширенной версией sample
в моем пакете:
library(devtools); install_github('kimisc', 'krlmlr')
library(kimisc)
sample.rows(subset(mydf, gender == "F"), 3)
Подробнее об этом ответе.