R语言stratified分层抽样出现因子水平抽样比例异常问题
问题根源
你遇到的抽样错位问题,完全是splitstackshape包中stratified()函数的size参数解析规则和你的预期不符导致的,这个函数根本不支持「通过命名小数向量给不同分层设置不同组内抽样比例」的用法,具体规则如下:
- 当
size传入单个小于1的数值时,函数才会在所有分层内统一按该比例抽样,自然保持原有类分布; - 当
size传入所有元素均≥1的整数型命名向量时,函数才会按名称匹配对应分层,抽取固定整数个样本——这也是你之前传整数时运行正常的原因; - 只要传入的命名向量里包含小于1的小数值,就会触发函数的异常解析逻辑:
- 如果所有小数加和等于1,函数会把这些值当成「最终抽中样本的组间权重占比」,而非每个组内的抽样比例,再加上因子类列和命名向量的匹配bug,会出现比例完全错位:你给BARBUNYA设置的0.097抽样比例实际被应用到了SEKER类,BARBUNYA类反而被分配了最小的0.038抽样比例,所以每次抽走的该类样本最少,迭代到最后占比异常偏高。
- 如果小数加和不等于1(比如你把BARBUNYA的比例改成0.5后,向量总和约1.4),函数会自动把所有小于1的数值向下取整为0,相当于默认该类不抽样,所以哪怕你把比例改成0.5,因为数值仍小于1,实际抽样量和设0.097时几乎没有差别。
正确实现方式
如果你的目的是迭代缩样时保持各类的原始占比不变,根本不需要给每个类单独传比例,每次迭代直接给size传单个保留比例即可,比如每次移除10%样本就设size=0.9,函数会自动在每个类内按90%比例抽样保留,类分布不会偏移。
如果确实需要给不同类设置不同的抽样/移除比例,不要依赖stratified的向量传参,直接按类分组抽样即可,参考代码:
library(dplyr) # 这里写每个类的保留比例=1-对应移除比例 keep_ratio <- c( "BARBUNYA" = 1 - 0.09712732, "BOMBAY" = 1 - 0.03835133, "CALI" = 1 - 0.11975608, "DERMASON" = 1 - 0.26052458, "HOROZ" = 1 - 0.14165014, "SEKER" = 1 - 0.14892366, "SIRA" = 1 - 0.19366689 ) while(nrow(beanclone) > 100) { beanclone <- beanclone %>% group_by(Class) %>% slice_sample(prop = unname(keep_ratio[cur_group()$Class])) %>% ungroup() print(table(beanclone$Class)) print(nrow(beanclone)) }
内容的提问来源于stack exchange,提问作者Pop
相关产品推荐
相关产品推荐

