首页 文章

基于条件向量在r中进行子集化

提问于
浏览
2

这是对我以前措辞不好的问题的重述 . (对于那些回复它的人,我感谢你们的努力,我很抱歉我的问题不像我应该那么清楚 . )我有一个大型数据集,其中一个子集可能如下所示:

a<-c(1,2,3,4,5,1)
b<-c("a","b","a","b","c","a")
c<-c("m","f","f","m","m","f")
d<-1:6
e<-data.frame(a,b,c,d)

如果我想根据特定条件得到第四列中的条目总和,我可以这样做:

attach(e)
total<-sum(e[which(a==3 & b=="a"),4])
detach(e)

但是,我有一个条件的“向量”(称之为condition_vector),其前四个元素看起来更像这样:

a==3 & b == "a"
a==2
a==1 & b=="a" & c=="m"
c=="f"

我想创建上面“总计”公式的“通用”版本,通过读入条件的condition_vector来生成总计的results_vector . 在此示例中,results_vector中的前四个条目将在概念上按如下方式计算:

results_vector[1]<-sum(e[which(a==3 & b=="a"),4])
results_vector[2]<-sum(e[which(a==2),4])
results_vector[3]<-sum(e[which(a==1 & b=="a" & c=="m"),4])
results_vector[4]<-sum(e[which(c=="f"),4])

我的实际数据集有20多个变量 . 因此,condition_vector中的每条记录都可以包含1到20个以上的条件(而不是1到3个条件,在本例中使用) .

有没有办法实现这一点,而不是使用解析(eval(text = ...方法(需要很长时间才能在相对较小的数据集上运行)?

提前感谢你提供的任何帮助(我再次道歉,我不像上次那样清楚) .

火花

2 回答

  • 2

    这里使用 eval(parse(text=..) 的解决方案,即使你发现它很慢:

    cond <- c('a==3 & b == "a"','a==2','a==1 & b=="a" & c=="x"','c=="f"')
    names(cond) <- cond
    results_vector <- lapply(cond,function(x)
                                  sum(dat[eval(parse(text=x)),"d"]))
    
    $`a==3 & b == "a"`
    [1] 3
    
    $`a==2`
    [1] 2
    
    $`a==1 & b=="a" & c=="m"`
    [1] 1
    
    $`c=="f"`
    [1] 11
    

    命名条件向量的优点是可以按条件访问结果 .

    results_vector[cond[2]]
     $`a==2`
      [1] 2
    
  • 0

    这是一个函数,它将每列中的条件作为参数(如果列中没有条件,那么 NA 作为参数)并在所选data.frame的选定列中求和:

    conds.by.col <- function(..., sumcol, DF)  #NA if not condition in a column
        {
         conds.ls <- list(...)
    
         res.ls <- vector("list", length(conds.ls))
         for(i in 1: length(conds.ls))
          {
           res.ls[[i]] <- which(DF[,i] == conds.ls[[i]])
          }
    
         res.ls <- res.ls[which(lapply(res.ls, length) != 0)]
    
         which_rows <- Reduce(intersect, res.ls)
    
         return(sum(DF[which_rows , sumcol]))
        }
    

    测试:

    a <- c(1,2,3,4,5,1)
        b <- c("a", "b", "a", "b", "c", "a")
        c <- c("m", "f", "f", "m", "m", "f")
        d <- 1:6
        e <- data.frame(a, b, c, d)
    
        conds.by.col(3, "a", "f", sumcol = 4, DF = e)
        #[1] 3
    

    对于多种情况, mapply

    #all conditions in a data.frame:
        myconds <- data.frame(con1 = c(3, "a", "f"),
                              con2 = c(NA, "a", NA),
                              con3 = c(1, NA, "f"),
                              stringsAsFactors = F)
    
        mapply(conds.by.col, myconds[1,], myconds[2,], myconds[3,], MoreArgs = list(sumcol = 4, DF = e))
    
        #con1 con2 con3 
        #   3   10    6
    

    我觉得“效率”不是你说的第一个看这个,但......

相关问题