【问题标题】:dplyr - How to collapse binary and mutually exclusive columns into 1?dplyr - 如何将二进制和互斥列折叠为 1?
【发布时间】:2020-05-11 21:51:04
【问题描述】:

假设我有一个具有以下结构的数据框:

|id  | segment1 | segment 2|
|----|----------|----------|
|1   | 1        |  0       |   
|2   | 1        |  0       |
|3   | 0        |  1       |
|4   | 1        |  0       |
|5   | 0        |  1       |

我如何对数据进行透视,而不是拥有 2 个“segment”列,而只有 1 个显示“segment1”或“segment2”的列?我在考虑pivot_longer,但我认为我们实际上不再制作数据框了。似乎肯定有比使用 mutateif_else 或创建新列并手动分配值更快的方法。

注意:这种转换不应产生更长的数据帧,因为我们只是折叠列

【问题讨论】:

  • 是的,tidyr 包中的pivot_longer 函数是正确的函数。然后过滤掉值==0的行。
  • @Dave2e ,那么我将如何使用 pivot_longer 来执行此操作?我认为它本质上使数据框更长

标签: r dplyr


【解决方案1】:

我们可以使用base R中的max.col获取第2列和第3列每行最大值的索引,使用该索引获取数据对应的列名

cbind(df1[1], segment = names(df1)[-1][max.col(df1[-1], 'first')])
#  id  segment
#1  1 segment1
#2  2 segment1
#3  3 segment2
#4  4 segment1
#5  5 segment2

或者使用tidyverse

library(dplyr)
library(tidyr)
df1 %>%
      pivot_longer(cols = -id, names_to = 'segment') %>%
      filter(as.logical(value)) %>%
      select(-value)
# A tibble: 5 x 2
#     id segment 
#  <int> <chr>   
#1     1 segment1
#2     2 segment1
#3     3 segment2
#4     4 segment1
#5     5 segment2

数据

df1 <- structure(list(id = 1:5, segment1 = c(1, 1, 0, 1, 0), segment2 = c(0, 
0, 1, 0, 1)), class = "data.frame", row.names = c(NA, -5L))

【讨论】:

    【解决方案2】:
          A = data.frame(id = c(1, 2, 3), 
                         segment1 = c(1, 1, 0), 
                         segment2 = c(0, 0, 1))
    
    tidyr::pivot_longer(A, c(segment1, segment2)) %>% 
                               filter(value == 1) %>% 
                                select(-value)
    # A tibble: 3 x 2
         id name    
      <dbl> <chr>   
    1     1 segment1
    2     2 segment1
    3     3 segment2
    

    【讨论】:

      【解决方案3】:

      这就是我会这样做的方式,你想要 pivot_longer 然后删除我认为的 0 值。

      library(tidyr)
      df <- data.frame(id = c(1, 2, 3, 4, 5),
                       segment1 = c(1, 1, 0, 1, 0),
                       segment2 = c(0, 0, 1, 0, 1))
      df %>%
        pivot_longer(cols = c("segment1", "segment2")) %>%
        filter(value == 1) %>%
        select(id, name)
      

      【讨论】:

        【解决方案4】:

        使用ifelse

        with(DF, ifelse(segment1 == 1, "segment1", "segment2"))
        
        library(dplyr)
        DF %>%
          mutate(segment = if_else(segment1 == 1, "segment1", "segment2"))
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-11
          • 1970-01-01
          • 2022-11-01
          • 2022-11-05
          • 2021-08-14
          • 1970-01-01
          • 2021-11-09
          • 2015-05-24
          相关资源
          最近更新 更多