选择保持分配百分比的行?

时间:2014-11-10 02:30:27

标签: r

我有一个带有变量" grade"的现有数据框。指示行/观察的类型。我的目标是从另一个数据框中选择更多这些类型的行,同时不超过现有数据框中每个成绩类型的最大百分比。我已经使用等级分配定义了一个命名向量:

gradeAllocation <- c("A" = 0, "B" = 0, "C" = .25, "D" = .40, "E" = .20, "F" = .10, "G" = .05) 

这表示数据框中每种成绩的最大百分比。现在,让我们说我想从另一个数据框中选择一个等级的混合但我不想选择太多,在选择后会给我超过每个等级类型的最大百分比。我基本上会在循环中为每个可用的新数据集执行此过程,但希望保持gradeAllocation向量给出的最大分布。

是否有可以帮助的包/功能?有关自定义代码的想法吗?

谢谢,约翰

2 个答案:

答案 0 :(得分:1)

这是一种方法

生成一些数据

nOriginal <- 1000
df1 <- data.frame(grade=sample(c('A','B','C','D','E','F','G'),1000,replace=TRUE),
                  indx=seq(1:nOriginal))

获取与每个成绩相对应的行

idx_a=which(df1$grade=='A')
idx_b=which(df1$grade=='B')
idx_c=which(df1$grade=='C')
idx_d=which(df1$grade=='D')
idx_e=which(df1$grade=='E')
idx_f=which(df1$grade=='F')
idx_g=which(df1$grade=='G')

根据规定的分布对行进行采样,该分布应总和为1。

location <- c("A" = 0, "B" = 0, "C" = .25, "D" = .40, "E" = .20, "F" = .10, "G" = .05) 
nSamples = 200
samp_idx_a <- sample(idx_a,nSamples*location["A"])
samp_idx_b <- sample(idx_b,nSamples*location["B"])
samp_idx_c <- sample(idx_c,nSamples*location["C"])
samp_idx_d <- sample(idx_d,nSamples*location["D"])
samp_idx_e <- sample(idx_e,nSamples*location["E"])
samp_idx_f <- sample(idx_f,nSamples*location["F"])
samp_idx_g <- sample(idx_g,nSamples*location["G"])

df_2 <- df1[c(samp_idx_a, samp_idx_b, samp_idx_c, samp_idx_d,
              samp_idx_e, samp_idx_f, samp_idx_g),]

检查结果

(percent_A = sum(df_2$grade=="A")/nrow(df_2)*100)
(percent_B = sum(df_2$grade=="B")/nrow(df_2)*100)
(percent_C = sum(df_2$grade=="C")/nrow(df_2)*100)
(percent_D = sum(df_2$grade=="D")/nrow(df_2)*100)
(percent_E = sum(df_2$grade=="E")/nrow(df_2)*100)
(percent_F = sum(df_2$grade=="F")/nrow(df_2)*100)
(percent_G = sum(df_2$grade=="G")/nrow(df_2)*100)

答案 1 :(得分:1)

正如@Fr.Flick指出的那样,无法保证这是可能的。在您的gradeAllocation中,采样分布总和为1.例如,如果您的测试数据集没有"D",则无法创建最多25%C的样本,15 %E,10%F,5%G,以及AB

此外,由于采样分布总和为1,如果您想要的样本大小为N,则每个等级的样本的必须由N * gradeAllocation给出。这是一种利用这一事实的方法,从具有700个样本并且均匀分布的数据集开始(每个等级中的数字相同),并且我们使用gradeAllocation给出的分布提取100的随机样本。

# sample dataset: 700 observations, grade distribution is uniform
set.seed(1)  # for reproducible example
data <- data.frame(grade=rep(LETTERS[1:7],each=100),x=rnorm(700))
# desired distribution in the sample
gradeAllocation <- c(A=0, B=0, C=.25, D=.40, E=.20, F=.10, G=.05) 

# you start here...
N <- 100    # sample size
get.sample<- function(g) data[sample(which(data$grade==g),N*gradeAllocation[g]),]
result <- do.call(rbind,lapply(LETTERS[1:7],get.sample))
# confirm distribution of grades in the sample
table(result$grade)   
#  A  B  C  D  E  F  G 
#  0  0 25 40 20 10  5