Ответ 1
Попробуйте следующее:
library(plyr)
ddply(df,.(ID),function(x) x[sample(nrow(x),500),])
У меня есть df, созданный почти 50 000 строк, распространенных в 15 разных идентификаторах (каждый идентификатор имеет тысячи наблюдений). df выглядит так:
ID Year Temp ph
1 P1 1996 11.3 6.80
2 P1 1996 9.7 6.90
3 P1 1997 9.8 7.10
...
2000 P2 1997 10.5 6.90
2001 P2 1997 9.9 7.00
2002 P2 1997 10.0 6.93
Я хочу взять 500 случайных строк для каждого ID (так 500 для P1, 500 для P2,....) и создать новый df. Я пытаюсь:
new_df<-df[df$ID %in% sample(unique(dfID),500),]
Но он принимает случайным образом один идентификатор, в то время как мне нужен 500 случайных строк для каждого ID.
Попробуйте следующее:
library(plyr)
ddply(df,.(ID),function(x) x[sample(nrow(x),500),])
Это доступно как функция sample_n
в dplyr
:
library(dplyr)
new_df <- df %>% group_by(ID) %>% sample_n(500)
Вот один подход в базе R.
Во-первых, предварительные данные выборки для работы с:
set.seed(1)
mydf <- data.frame(ID = rep(1:3, each = 5), matrix(rnorm(45), ncol = 3))
mydf
# ID X1 X2 X3
# 1 1 -0.6264538 -0.04493361 1.35867955
# 2 1 0.1836433 -0.01619026 -0.10278773
# 3 1 -0.8356286 0.94383621 0.38767161
# 4 1 1.5952808 0.82122120 -0.05380504
# 5 1 0.3295078 0.59390132 -1.37705956
# 6 2 -0.8204684 0.91897737 -0.41499456
# 7 2 0.4874291 0.78213630 -0.39428995
# 8 2 0.7383247 0.07456498 -0.05931340
# 9 2 0.5757814 -1.98935170 1.10002537
# 10 2 -0.3053884 0.61982575 0.76317575
# 11 3 1.5117812 -0.05612874 -0.16452360
# 12 3 0.3898432 -0.15579551 -0.25336168
# 13 3 -0.6212406 -1.47075238 0.69696338
# 14 3 -2.2146999 -0.47815006 0.55666320
# 15 3 1.1249309 0.41794156 -0.68875569
Во-вторых, выборка:
do.call(rbind,
lapply(split(mydf, mydf$ID),
function(x) x[sample(nrow(x), 3), ]))
# ID X1 X2 X3
# 1.2 1 0.1836433 -0.01619026 -0.1027877
# 1.1 1 -0.6264538 -0.04493361 1.3586796
# 1.5 1 0.3295078 0.59390132 -1.3770596
# 2.10 2 -0.3053884 0.61982575 0.7631757
# 2.9 2 0.5757814 -1.98935170 1.1000254
# 2.8 2 0.7383247 0.07456498 -0.0593134
# 3.13 3 -0.6212406 -1.47075238 0.6969634
# 3.12 3 0.3898432 -0.15579551 -0.2533617
# 3.15 3 1.1249309 0.41794156 -0.6887557
Существует также strata
из пакета sampling
, что удобно, если вы хотите выбирать разные размеры из каждой группы:
# install.packages("sampling")
library(sampling)
set.seed(1)
x <- strata(mydf, "ID", size = c(2, 3, 2), method = "srswor")
getdata(mydf, x)
# X1 X2 X3 ID ID_unit Prob Stratum
# 2 0.1836433 -0.01619026 -0.1027877 1 2 0.4 1
# 5 0.3295078 0.59390132 -1.3770596 1 5 0.4 1
# 6 -0.8204684 0.91897737 -0.4149946 2 6 0.6 2
# 8 0.7383247 0.07456498 -0.0593134 2 8 0.6 2
# 9 0.5757814 -1.98935170 1.1000254 2 9 0.6 2
# 14 -2.2146999 -0.47815006 0.5566632 3 14 0.4 3
# 15 1.1249309 0.41794156 -0.6887557 3 15 0.4 3
Подход, если по идентификаторам есть < 500. Здесь я использовал набор mtcars:
n <- 8
df <- mtcars
df$ID <- df$cyl
FUN <- function(x, n) {
if (length(x) <= n) return(x)
x[x %in% sample(x, n)]
}
df[unlist(lapply(split(1:nrow(df), df$ID), FUN, n = 8)), ]
mydata1 is your original data(not tested)
mydata2<- split(mydata1,mydata1$ID)
names(mydata2)<-paste0("mydata2",1:length(levels(ID)))
mysample<-Map(function(x) x[sample((1:nrow(x)),size=500,replace=FALSE),], mydata2)
library(plyr)# for rbinding the mysample
ldply(mysample)
Хотя это не очень элегантное решение, но оно может сработать.
library(data.table)
df <- data.table(df)
f <- list()
for(i in unique(df1$ID)){
f[[i]] <- df1[id == i][sample(.N,(500))]
}
dfnew <- rbindlist(f)
library(data.table) #1
df <- data.table(df) #2
df[,group_num := sample(2,.N,replace = TRUE,prob = c(500,.N-500)/.N),by = "ID"] #3
df_sample = df[group_num == 1,] #4
или вы можете изменить строки № 3 и № 4 на:
df[,random_num := sample(.N,.N),by="ID"]
df_sample = df[random_num <=500,]