逐组采样数据的子集,样本大小等于数据帧的另一个子集

时间:2014-02-21 22:28:18

标签: r subset plyr

这是我的假设数据框;

location<- as.factor(rep(c("town1","town2","town3","town4","town5"),100))
visited<- as.factor(rbinom(500,1,.4)) #'Yes or No' variable
variable<- rnorm(500,10,2)
id<- 1:500
DF<- data.frame(id,location,visited,variable)

我想创建一个新的数据框,其中每个位置的0和1的数量相等。我想通过对每个位置随机抽取0来实现这一目标(因为0比1更多)。

我发现这个解决方案是按组进行采样;

library(plyr)
ddply(DF[DF$visited=="0",],.(location),function(x) x[sample(nrow(x),size=5),])

我为size参数输入了'5',因此代码会运行,但我无法弄清楚如何将'size'参数设置为等于DF $访问的观察数== 1。

我怀疑答案可能出在我审核过的其他问题中,但是对我来说实施起来有点太高级了。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

使用ddply的关键是理解它会:

  1. 将原始数据框按分组缩小为较小的数据框
  2. 然后,对于每个组,它将调用您给它的函数,其作用是该数据框转换为新的数据框*
  3. 最后,它会将所有小变形数据帧重新拼接在一起。
  4. 考虑到这一点,这是(我认为)解决您的问题的方法。

    sampleFunction <- function(df) {
      # Determine whether visited==1 or visited==0 is less common for this location, 
      # and use that count as our sample size.
      n <- min(nrow(df[df$visited=="1",]), nrow(df[df$visited=="0",]))
      # Sample n from the two groups (visited==0 and visited==1).
      ddply(df, .(visited), function(x) x[sample(nrow(x), size=n),])
    }
    
    newDF <- ddply(DF,.(location),sampleFunction)
    
    # Just a quick check to make sure we have the equal counts we were looking for.
    ddply(newDF, .(location, visited), summarise, N=length(variable))
    

    如何运作

    ddply只会按位置缩短DF并应用sampleFunction,这会带来繁重的工作。

    sampleFunction获取一个较小的数据框(在您的情况下,每个位置一个),并从中获取相同数量的visited==1visited==0。它是如何做到的?通过第二次调用ddply:这次,使用location将其分解,以便我们可以从1和0进行采样。

    另外请注意,我们根据每个位置(0或1)的出现次数较少来计算每个位置的样本大小,因此即使不总是超过1,也可以使用此解决方案。