【问题标题】:Create new columns based on comma-separated values in another column in R [duplicate]基于R中另一列中的逗号分隔值创建新列[重复]
【发布时间】:2020-10-31 14:21:11
【问题描述】:

我有一些类似于下面的数据。

df <- data.frame(id = 1:5, tags = c("A,B,AB,C", "C", "AB,E", NA, "B,C"))
df

#   id     tags
# 1  1 A,B,AB,C
# 2  2        C
# 3  3     AB,E
# 4  4     <NA>
# 5  5      B,C

我想为“标签”列中的每个标签创建一个新的虚拟变量列,从而生成如下数据框:

correct_df <- data.frame(id = 1:5, 
                     tags = c("A,B,AB,C", "C", "AB,E", NA, "B,C"),
                     A = c(1, 0, 0, 0, 0),
                     B = c(1, 0, 0, 0, 1),
                     C = c(1, 1, 0, 0, 1),
                     E = c(0, 0, 1, 0, 0),
                     AB = c(1, 0, 1, 0, 0)
                    )
correct_df

#   id     tags A B C E AB
# 1  1 A,B,AB,C 1 1 1 0  1
# 2  2        C 0 0 1 0  0
# 3  3     AB,E 0 0 0 1  1
# 4  4     <NA> 0 0 0 0  0
# 5  5      B,C 0 1 1 0  0

其中一个挑战是确保“A”列的“A”标签只有 1,例如“AB”标签就没有 1。出于这个原因,以下内容不起作用,因为“A”为“AB”标签获得了 1:

df <- df %>%
  mutate(A = ifelse(grepl("A", tags, fixed = T), 1, 0))
df

#   id     tags A
# 1  1 A,B,AB,C 1
# 2  2        C 0
# 3  3     AB,E 1 < Incorrect
# 4  4     <NA> 0
# 5  5      B,C 0

另一个挑战是以编程方式进行。我可能会处理为每个标签手动创建列的解决方案,但最好不要假设需要预先创建哪些标签列,因为可能有许多不同的标签。是否有一些我忽略的相对简单的解决方案?

【问题讨论】:

  • splitstackshape::cSplit_e(df, "tags", sep = ',', fill = 0, type = "character")
  • 完美。这个解决方案(遵循this question 的答案)可以满足我的所有需求,而且简短而甜蜜。

标签: r dataframe


【解决方案1】:

这行得通吗:

> library(tidyr)
> library(dplyr)
> df %>% separate_rows(tags) %>% mutate(A = case_when(tags == 'A' ~ 1, TRUE ~ 0),
+                                       B = case_when(tags == 'B' ~ 1, TRUE ~  0),
+                                       C = case_when(tags == 'C' ~ 1,  TRUE ~  0),
+                                       E = case_when(tags == 'E' ~ 1,  TRUE ~ 0),
+                                       AB = case_when(tags == 'AB' ~ 1,  TRUE ~ 0)) %>% 
+   group_by(id) %>% mutate(tags = toString(tags)) %>% group_by(id, tags) %>% summarise(across(A:AB, sum))
`summarise()` regrouping output by 'id' (override with `.groups` argument)
# A tibble: 5 x 7
# Groups:   id [5]
     id tags            A     B     C     E    AB
  <int> <chr>       <dbl> <dbl> <dbl> <dbl> <dbl>
1     1 A, B, AB, C     1     1     1     0     1
2     2 C               0     0     1     0     0
3     3 AB, E           0     0     0     1     1
4     4 NA              0     0     0     0     0
5     5 B, C            0     1     1     0     0
> 

【讨论】:

    【解决方案2】:

    这里有一个解决方案:

    library(dplyr)
    library(stringr)
    library(magrittr)
    library(tidyr)
    
    #Data
    df <- data.frame(id = 1:5, tags = c("A,B,AB,C", "C", "AB,E", NA, "B,C"))
    
    #Separate into rows
    df %<>% mutate(t2 = tags) %>% separate_rows(t2, sep = ",")
    
    #Create a presence/absence column
    df %<>% mutate(pa = 1)
    
    #Pivot wider and use the presence/absence
    #column as entries; fill with 0 if absent
    df %<>% pivot_wider(names_from = t2, values_from = pa, values_fill = 0)
    
    df
    # # A tibble: 5 x 8
    #      id tags         A     B    AB     C     E  `NA`
    #   <int> <chr>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    # 1     1 A,B,AB,C     1     1     1     1     0     0
    # 2     2 C            0     0     0     1     0     0
    # 3     3 AB,E         0     0     1     0     1     0
    # 4     4 NA           0     0     0     0     0     1
    # 5     5 B,C          0     1     0     1     0     0
    

    编辑:更新代码以使其能够保留标签列。对不起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      • 2021-06-01
      • 2022-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多