【问题标题】:Multiple, flexible logical column comparison in Data.tableData.table 中的多个灵活的逻辑列比较
【发布时间】:2019-05-28 17:27:29
【问题描述】:

我想在 R 中比较数据表中的多个列,并且我不想对它们进行硬编码。例如,请参见下面的简单示例:

###########
#Setup data
###########

set.seed(2)
fill = data.table(n=1:7)
Tp=3

for(t in 1:Tp){ 
  set(x = fill, j = paste0('v',t), value = sample(0:10,7))
}

fill[1,paste0('v',3):=0]
fill[5,paste0('v',2):=0]
fill[5,paste0('v',3):=0]

for(t in 1:Tp){ 
  fill[,paste0('v',t,'prm'):=get(paste0('v',t))]
}

fill[1,paste0('v',1,'prm'):=0] 
fill[2,paste0('v',2,'prm'):=1]   
fill[5,paste0('v',3,'prm'):=1]  
fill[7,paste0('v',3,'prm'):=2]   

所以数据是:

> fill
   n v1 v2 v3 v1prm v2prm v3prm
1: 1  2  9  0     0     9     0
2: 2  7  4  8     7     1     8
3: 3  5 10  9     5    10     9
4: 4  1  8  1     1     8     1
5: 5  6  0  0     6     0     1
6: 6  8  7  0     8     7     0
7: 7  0  0  6     0     0     2  

我想将每一列与其'prm'进行数字比较,如下所示:

fill[v1==v1prm & v2==v2prm & v3==v3prm]

所以输出是:

> fill[v1==v1prm & v2==v2prm & v3==v3prm]

   n v1 v2 v3 v1prm v2prm v3prm
1: 3  5 10  9     5    10     9
2: 4  1  8  1     1     8     1
3: 6  8  7  0     8     7     0

但我不想对此进行硬编码,因为我可能会使用超过 3 列。另外,我可能想使用其他比较,例如...

> fill[v1>v1prm & v2==v2prm & v3==v3prm]

   n v1 v2 v3 v1prm v2prm v3prm
1: 1  2  9  0     0     9     0

【问题讨论】:

    标签: r boolean data.table logic


    【解决方案1】:

    通过Map在这里使用函数式方法:

    ## set some variable names
    pre <- paste0("v", 1:3)
    pst <- paste0(pre, "prm")
    
    ## select where they match using `==` and Reduce to combine with a `&` (logical AND)
    fill[Reduce(`&`, Map(`==`, mget(pre), mget(pst)))]
    #   n v1 v2 v3 v1prm v2prm v3prm
    #1: 3  5 10  9     5    10     9
    #2: 4  1  8  1     1     8     1
    #3: 6  8  7  0     8     7     0
    

    扩展此逻辑以循环不同的逻辑比较:

    funs <- c(`>`, `==`, `==`)
    fill[Reduce(`&`, Map(function(pr,ps,f) f(pr,ps), mget(pre), mget(pst), funs))]
    #   n v1 v2 v3 v1prm v2prm v3prm
    #1: 1  2  9  0     0     9     0
    

    【讨论】:

      【解决方案2】:

      功能性方法的答案很酷,但我更喜欢行人eval/parse,因为它更容易阅读/维护:

      lhs = paste0('v', 1:3)
      fns = c('>', '==', '==')
      rhs = paste0(pre, 'prm')
      
      fill[eval(parse(text = paste(lhs, fns, rhs, collapse = '&')))]
      #   n v1 v2 v3 v1prm v2prm v3prm
      #1: 1  2  9  0     0     9     0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-30
        • 2021-09-13
        相关资源
        最近更新 更多