【问题标题】:use ifelse statement in R data.table column calculation dependent on value first row在 R data.table 列计算中使用 ifelse 语句取决于值第一行
【发布时间】:2021-06-02 10:39:03
【问题描述】:

我必须对大型数据表(+30m 行)(实际上很多)做一些正则表达式。其中一列要么只是一个重复的字符串(每一行都相同或缺失),而另一列是每行不同的字符串。现在,如果第一列值丢失或传递了其他一些正则表达式,我不想执行正则表达式并只返回 FALSE,如果它没有丢失,我想查看列是否匹配。这是因为我确实需要它来处理数千个 data.tables,并且因为正则表达式需要几秒钟,所以我想包含一个 ifelse 语句,如果该语句为 FALSE,则甚至不会尝试正则表达式。

这是我尝试过的,但这些都不起作用(我也尝试过 fifelseif_else

library(data.table)
set.seed(10)
data_table_test <-
  data.table(col  = rep("c", 1e6),
             col2 =  paste(
               sample(letters, 1e6,
                      replace = T),
               sample(letters, 1e6,
                      replace = T),
               sep = ""
             ))

data_table_test2 <-
  data.table(col  = rep(NA, 1e6),
             col2 =  paste(
               sample(letters, 1e6,
                      replace = T),
               sample(letters, 1e6,
                      replace = T),
               sep = ""
             ))


data_table_test[, ':='(matching_letter_1   = stringi::stri_detect_fixed(col2, col),
                       matching_letter_2   = ifelse(is.na(data_table_test[1, col ]), F, stringi::stri_detect_fixed(col2, col))),]

data_table_test2[, ':='(matching_letter_1   = stringi::stri_detect_fixed(col2, col),
                       matching_letter_2   = ifelse(is.na(data_table_test2[1, col ]), F, stringi::stri_detect_fixed(col2, col))),]

这确实有效,但速度较慢

data_table_test2[, ':='(matching_letter_1   = stringi::stri_detect_fixed(col2, col)), ][, ':='(matching_letter_1 = fifelse(is.na(matching_letter_1),  F, matching_letter_1)), ]

编辑 预期的输出应该是这样的

data_table_test[matching_letter_1 == TRUE]

应该和

一样

data_table_test[matching_letter_2 == TRUE]

data_table_test2[matching_letter_1 == TRUE]

应该和(都是空的data.tables)一样

data_table_test2[matching_letter_2 == TRUE]

一个缓慢但实用的 tidyverse 解决方案是这样的:

data_table_test %>%
  as_tibble() %>%
  rowwise() %>%
  mutate(matching_letter = ifelse(is.na(data_table_test$col[1]), F, stringi::stri_detect_fixed(col2, col))) %>%
  filter(matching_letter)


# A tibble: 75,772 x 3
# Rowwise: 
   col   col2  matching_letter
   <chr> <chr> <lgl>          
 1 c     cb    TRUE           
 2 c     ce    TRUE           
 3 c     yc    TRUE           
 4 c     ch    TRUE           
 5 c     ic    TRUE           
 6 c     gc    TRUE           
 7 c     cg    TRUE           
 8 c     lc    TRUE           
 9 c     ci    TRUE           
10 c     zc    TRUE           
# ... with 75,762 more rows


data_table_test2 %>%
  as_tibble() %>%
  rowwise() %>%
  mutate(matching_letter = ifelse(is.na(data_table_test2$col[1]), F, stringi::stri_detect_fixed(col2, col))) %>%
  filter(matching_letter)



# A tibble: 0 x 3
# Rowwise: 
# ... with 3 variables: col <lgl>, col2 <chr>, matching_letter <lgl>

编辑 2 这段代码可以解决问题,但不是我需要的解决方案,因为我需要测试许多列组合。我需要 data.table 操作中的 if 语句

if(is.na(data_table_test[1, col ])){
  data_table_test[, matching_letter := F, ]
}else{
  data_table_test[, matching_letter_1 := stringi::stri_detect_fixed(col2, col),]
}

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    我没有 tidyverse 来比较预期输出,请包括没有如此严重依赖关系的预期输出。

    setmatchingletter = function(x) {
      stopifnot(nrow(x)>0L, c("col","col2")%in%names(x))
      v = if (is.na(x$col[1L])) FALSE else {
        stringi::stri_detect_fixed(x$col2, x$col)
      }
      set(x, , "matching_letter", v)
    }
    
    setmatchingletter(data_table_test)
    data_table_test[matching_letter==TRUE]
    
    setmatchingletter(data_table_test2)
    data_table_test2[matching_letter==TRUE]
    

    此解决方案假定 stringi::stri_detect_fixed 是“矢量化”的,这与问题中的使用不同。

    【讨论】:

    • 这基本上是if(is.na(data_table_test[1, col ])){ data_table_test[, matching_letter := F, ] }else{ data_table_test[, matching_letter_1 := stringi::stri_detect_fixed(col2, col),] }。这适用于 MRE,但对于我的实际代码,因为我想对 30+ 列组合进行测试,所以 if 语句应该以某种方式出现在 data.table 操作中,而不是在它之外
    • @LSmeets 所以请扩展您的示例以涵盖“我需要测试许多列组合”。
    猜你喜欢
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多