【问题标题】:Split a dataframe column with a comma-separated list of tags使用逗号分隔的标签列表拆分数据框列
【发布时间】:2020-05-28 07:28:21
【问题描述】:

我正在处理以标签为特征的产品数据集。也就是说,它们具有包含在逗号分隔的单词列表中的属性。例如,

data.frame(
   id = c(11, 12, 13),
   tags =c("wood,small,old","big,iron,artistic", "pretty,wood")
)

我想为每个标签将标签列分成不同的逻辑列,即

| id | wood | iron | small |  big |  old | artistic | pretty | 
------------------------------------------------------------
| 11 |  TRUE| FALSE|   TRUE| FALSE|  TRUE|     FALSE|   FALSE|
| 12 | FALSE|  TRUE|  FALSE|  TRUE| FALSE|      TRUE|   FALSE|
| 13 |  TRUE| FALSE|  FALSE| FALSE| FALSE|     FALSE|    TRUE|

我尝试使用tidyr包中的separate函数,但是标签是无序的,很难为每个标签做一列。

我找到了使用dplyr 包中的mutate 并为每个标签手动创建一列的解决方案,

has_tag <- function(tag, tags) {
    strsplit(tags, ",") %>% map_lgl(function(x) tag %in% x)
}

df %>% 
    mutate(
        wood = has_tag("wood", tags),
        iron = has_tag("iron", tags),
        ...
    )

但未来可能会出现新标签,我想让它可扩展。

¿有什么方法可以轻松做到吗?

【问题讨论】:

标签: r dataframe tidyr data-cleaning


【解决方案1】:

你可以这样做:

library(tidyverse)
df %>% 
   separate_rows(tags) %>%
    mutate(val = TRUE) %>%
    spread(tags, val, FALSE)
      id artistic   big  iron   old pretty small  wood
    1 11    FALSE FALSE FALSE  TRUE  FALSE  TRUE  TRUE
    2 12     TRUE  TRUE  TRUE FALSE  FALSE FALSE FALSE
    3 13    FALSE FALSE FALSE FALSE   TRUE FALSE  TRUE

使用基础 R 需要一些步骤:

as.data.frame.matrix(xtabs(f~ind+values,
      cbind(stack(setNames(strsplit(as.character(df$tags),","),df$id)),f = 1))>0)

   artistic   big  iron   old pretty small  wood
11    FALSE FALSE FALSE  TRUE  FALSE  TRUE  TRUE
12     TRUE  TRUE  TRUE FALSE  FALSE FALSE FALSE
13    FALSE FALSE FALSE FALSE   TRUE FALSE  TRUE

【讨论】:

  • 这很优雅!
  • 这正是我所需要的。谢谢你。我非常喜欢在 tidyverse 之外不需要任何包。
【解决方案2】:

我们可以使用splitstackshape 中的cSplit_e 创建一个二进制列,然后通过删除前缀来使用rename

library(splitstackshape)
library(dplyr)
library(stringr)
cSplit_e(df1, 'tags', sep=",", type = 'character', fill = 0, drop = TRUE) %>%
    mutate_at(-1, as.logical) %>%
    rename_at(-1, ~ str_remove(., 'tags_'))
#  id artistic   big  iron   old pretty small  wood
#1 11    FALSE FALSE FALSE  TRUE  FALSE  TRUE  TRUE
#2 12     TRUE  TRUE  TRUE FALSE  FALSE FALSE FALSE
#3 13    FALSE FALSE FALSE FALSE   TRUE FALSE  TRUE

或者更简洁

library(qdapTools)
cbind(df1[1],  mtabulate(strsplit(as.character(df1$tags), ",")))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多