【问题标题】:Using paste to create logical expression for data frame subset使用粘贴为数据框子集创建逻辑表达式
【发布时间】:2014-12-08 19:04:52
【问题描述】:

我有两个数据框,removedat(实际的数据框)。 remove 指定了在dat 中找到的因子变量的各种组合,以及要采样的数量 (remove$cases)。

可重现的例子:

set.seed(83)
dat <- data.frame(RateeGender=sample(c("Male", "Female"), size = 1500, replace = TRUE), 
                  RateeAgeGroup=sample(c("18-39", "40-49", "50+"), size = 1500, replace = TRUE),
                  Relationship=sample(c("Direct", "Manager", "Work Peer", "Friend/Family"), size = 1500, replace = TRUE),
                  X=rnorm(n=1500, mean=0, sd=1),
                  y=rnorm(n=1500, mean=0, sd=1),
                  z=rnorm(n=1500, mean=0, sd=1))

我想要完成的是从remove 连续读取并将其用于子集dat。我目前的方法如下:

remove <- expand.grid(RateeGender = c("Male", "Female"), 
                      RateeAgeGroup = c("18-39","40-49", "50+"),
                      Relationship = c("Direct", "Manager", "Work Peer", "Friend/Family"))
remove$cases <- c(36,34,72,58,47,38,18,18,15,22,17,10,24,28,11,27,15,25,72,70,52,43,21,27)

# For each row of remove (combination of factor levels:)
for (i in 1:nrow(remove)) {
  selection <- character()
  # For each column of remove (particular selection):
  for (j in 1:(ncol(remove)-1)){
    add <- paste0("dat$", names(remove)[j], ' == "', remove[i,j], '" & ')
    selection <- paste0(selection, add)
  }
  selection <- sub(' & $', '', selection) # Remove trailing ampersand
  cat(selection, sep = "\n") # What does selection string look like?
  tmp <- sample(dat[selection, ], size = remove$cases[i], replace = TRUE)
}

循环运行时cat() 的输出看起来正确,例如:dat$RateeGender == "Male" &amp; dat$RateeAgeGroup == "18-39" &amp; dat$Relationship == "Direct",如果我将其粘贴到dat[dat$RateeGender == "Male" &amp; dat$RateeAgeGroup3 == "18-39" &amp; dat$Relationship == "Direct" ,],我得到正确的子集。

但是,如果我按照dat[selection, ] 编写的方式运行循环,则每个子集仅返回NAs。如果我使用subset(),我会得到相同的结果。请注意,我在上面有replace = TRUE 仅仅是因为随机抽样。在实际应用中,每个组合的案例总是比要求的多。

我知道我可以通过这种方式使用paste()lm() 和其他函数动态构造公式,但在将其转换为使用[,] 时显然缺少一些东西。

任何建议将不胜感激!

【问题讨论】:

    标签: r subset


    【解决方案1】:

    您不能使用[subset 对子集描述的字符表达式。如果你想这样做,你必须构造整个表达式,然后使用eval。也就是说,使用merge 有更好的解决方案。例如,让我们获取dat 中与remove 中前两行匹配的所有条目:

    merge(dat, remove[1:2,])
    

    如果我们想要所有不匹配这两个的行,那么:

    subset(merge(dat, remove[1:2,], all.x=TRUE), is.na(cases))
    

    这是假设您要连接两个表中具有相同名称的列。如果您有大量数据,您应该考虑使用data.table,因为这种操作非常快。

    【讨论】:

      【解决方案2】:

      在我意识到在类别大小小于所需样本数量的情况下它不能满足您的要求之前,我赞成 BrodieG 的回答。 (事实上​​,他的方法根本没有真正进行抽样,但我认为这是解决不同问题的优雅解决方案,所以我不会推翻我的投票。您可以使用类似的拆分策略,如下所示与该数据.frame 作为输入。)。

      sub <- lapply( split(dat, with(dat, paste(RateeGender,  # split vector
                                                RateeAgeGroup,
                                                Relationship, sep="_")) ), 
                   function (d) { n=  with(remove, remove[
                                            RateeGender==d$RateeGender[1]&
                                            RateeAgeGroup==d$RateeAgeGroup[1]& 
                                            Relationship==d$Relationship[1], 
                                                                   "cases"])
                                            cat(n); 
                                            sample(d, n, repl=TRUE) } )
      

      【讨论】:

        猜你喜欢
        • 2021-12-11
        • 2019-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多