【问题标题】:How to merge two true/false variables in R?如何在 R 中合并两个真/假变量?
【发布时间】:2020-07-18 13:54:28
【问题描述】:

我在 data.frame 中有四个变量,如下所示,它延续了数千行:

One      Two      Three    Four 

TRUE     TRUE     FALSE    FALSE
FALSE    TRUE     TRUE     TRUE
TRUE     FALSE    FALSE    TRUE
TRUE     TRUE     TRUE     FALSE
FALSE    TRUE     FALSE    TRUE
FALSE    FALSE    TRUE     FALSE
TRUE     FALSE    FALSE    TRUE

我想创建两个新变量,一个合并第一列和第二列,第二个合并第三列和第四列。因此,如果两列中的一个或两个都显示为 TRUE,则每个新列将显示 TRUE,如果两者都为假,则将显示 FALSE。结果数据如下所示:

One      Two      OneTwo     Three    Four    ThreeFour

TRUE     TRUE     TRUE       FALSE    FALSE   FALSE
FALSE    TRUE     TRUE       TRUE     TRUE    TRUE
TRUE     FALSE    TRUE       FALSE    TRUE    TRUE
TRUE     TRUE     TRUE       FALSE    FALSE   FALSE
FALSE    FALSE    FALSE      FALSE    TRUE    TRUE
FALSE    FALSE    FALSE      TRUE     FALSE   TRUE
TRUE     FALSE    TRUE       FALSE    TRUE    TRUE

任何帮助将不胜感激。我查看了其他一些问题,但找不到具体的方法。

【问题讨论】:

    标签: r


    【解决方案1】:

    使用包dplyr你可以这样做:

    library(dplyr)
    data <- data %>% mutate(
       OneTwo = as.logical(One + Two),
       ThreeFour = as.logical(Three + Four))
    

    这是有效的,因为TRUEFALSE 实际上被计算机保存为 1 和 0。 R 然后将大于 0 的值编码为TRUE。为了更“正确”,您还可以使用此代码,在将它们转换为逻辑之前取回 0 和 1:

    library(dplyr)
    data <- data %>%
       mutate(
        OneTwo = as.logical(pmax(One, Two)),
        ThreeFour = as.logical(pmax(One, Two)))
    

    【讨论】:

    • 我喜欢简洁。为什么不使用|?那么你就不必强迫回到逻辑上。此外,您使用 rowwise 进行的编辑是......好的。没有分组的类似方式是pmax,但您的初始方式仍然是|
    • 关于pmax 的好点,我会相应地编辑我的帖子。你能解释一下| 的意思吗?
    • One | Two 等价于as.logical(One + Two)
    • 查看?Logical中的最后一个示例。
    【解决方案2】:

    您可以通过矢量化的方式实现这一点:

    tf <- c(TRUE, FALSE)
    nm <- names(df)
    
    # Merge
    res <- cbind(df, df[tf] | df[rev(tf)])
    
    # Set the names
    names(res) <- c(nm, paste0(nm[tf], nm[rev(tf)]))
    

    给予:

         V1    V2    V3    V4    V5    V6 V1V2  V3V4  V5V6
    1 FALSE  TRUE  TRUE  TRUE  TRUE FALSE TRUE  TRUE  TRUE
    2  TRUE  TRUE  TRUE  TRUE FALSE  TRUE TRUE  TRUE  TRUE
    3  TRUE  TRUE  TRUE FALSE  TRUE FALSE TRUE  TRUE  TRUE
    4  TRUE FALSE FALSE FALSE  TRUE  TRUE TRUE FALSE  TRUE
    5  TRUE  TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
    

    数据:

    set.seed(5)
    df <- as.data.frame(matrix(sample(c(TRUE, FALSE), 30, replace = TRUE), 5))
    

    【讨论】:

      【解决方案3】:

      适用于许多列的通用解决方案。在这里,最后两列是比较每对列的结果。

      cbind(df, do.call(cbind, lapply(seq(length(df)/2) * 2, function(i) df[[i-1]] | df[[i]])))
          One   Two Three  Four     1     2
      1  TRUE  TRUE FALSE FALSE  TRUE FALSE
      2 FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
      3  TRUE FALSE FALSE  TRUE  TRUE  TRUE
      4  TRUE  TRUE  TRUE FALSE  TRUE  TRUE
      5 FALSE  TRUE FALSE  TRUE  TRUE  TRUE
      6 FALSE FALSE  TRUE FALSE FALSE  TRUE
      7  TRUE FALSE FALSE  TRUE  TRUE  TRUE
      

      【讨论】:

        【解决方案4】:

        这是一种可以扩展到任意数量的列的方法。

        #Create group of every two columns
        cols <- ceiling(seq_len(ncol(df))/2)
        #Create column names
        new_col <- tapply(names(df), cols, paste0, collapse = "")
        #Split every two columns and use `|`.
        df[new_col] <- sapply(split.default(df, cols), function(x) Reduce(`|`, x))
        df
        
        #    One   Two Three  Four OneTwo ThreeFour
        #1  TRUE  TRUE FALSE FALSE   TRUE     FALSE
        #2 FALSE  TRUE  TRUE  TRUE   TRUE      TRUE
        #3  TRUE FALSE FALSE  TRUE   TRUE      TRUE
        #4  TRUE  TRUE  TRUE FALSE   TRUE      TRUE
        #5 FALSE  TRUE FALSE  TRUE   TRUE      TRUE
        #6 FALSE FALSE  TRUE FALSE  FALSE      TRUE
        #7  TRUE FALSE FALSE  TRUE   TRUE      TRUE
        

        【讨论】:

          【解决方案5】:

          你可以试试这个:

          OneTwo <- ifelse(One == TRUE & Two == TRUE, TRUE,
                           ifelse(One == TRUE & Two == FALSE, TRUE,
                                  ifelse(One == FALSE & Two == TRUE, TRUE,
                                         ifelse(One == FALSE & Two == FALSE, FALSE)))
          

          【讨论】:

            【解决方案6】:

            使用来自dplyr 包的case_when

            library(dplyr)
            df %>% 
              mutate(OneTwo = case_when(One == TRUE & Two == TRUE ~ TRUE,
                                        One == FALSE & Two == TRUE ~ TRUE,
                                        One == TRUE & Two == FALSE ~ TRUE,
                                        One == FALSE & Two == FALSE ~ FALSE),
                     ThreeFour = case_when(Three == TRUE & Four == TRUE ~ TRUE,
                                           Three == FALSE & Four == TRUE ~ TRUE,
                                           Three == TRUE & Four == FALSE ~ TRUE,
                                           Three == FALSE & Four == FALSE ~ FALSE))
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多