将逗号分隔的关键字转换为数据框中的列

时间:2015-03-08 11:56:27

标签: r

我有以下数据框:

id    keywords
---   --------
1     Red
2     Red, Blue
3     Green, Blue

我想重塑它:

id    Red     Blue    Green
---   -----   -----   -----   
1     T       F       F
2     T       T       F
3     F       T       T

有什么想法吗?

5 个答案:

答案 0 :(得分:4)

将字符串拆分为子字符串后,您可以从mtabulate尝试qdapTools

library(qdapTools)
data.frame(id=df1$id,!!mtabulate(strsplit(df1$keywords, ', ')))
#   id  Blue Green   Red
#1  1 FALSE FALSE  TRUE
#2  2  TRUE FALSE  TRUE
#3  3  TRUE  TRUE FALSE

或使用base R

data.frame(id=df1$id,!!t(sapply(strsplit(df1$keywords, ', '),
   function(x) table(factor(x, levels=c('Red', 'Blue', 'Green'))))))
#  id   Red  Blue Green
#1  1  TRUE FALSE FALSE
#2  2  TRUE  TRUE FALSE
#3  3 FALSE  TRUE  TRUE

答案 1 :(得分:3)

# using R base 
#
# your data
d <- data.frame(
id=1:3,
keywords=c('Red','Red,Blue','Green,Blue'),
stringsAsFactors=F)
# 
cls <- unique(unlist(strsplit(d$keywords,split=',')))
dl <- sapply(cls,function(n)sapply(d$keywords,grepl,pattern=n))
# print result
d <- cbind(d,dl)
d
  id   keywords   Red  Blue Green
1  1        Red  TRUE FALSE FALSE
2  2   Red,Blue  TRUE  TRUE FALSE
3  3 Green,Blue FALSE  TRUE  TRUE
# d$Green is atomic

答案 2 :(得分:2)

这是另一种可能的方法

## vector for matching
nm <- c("Red", "Blue", "Green")

dc <- do.call(rbind, lapply(strsplit(df$keywords, ", "), function(x) {
    length(x) <- nrow(df)
    setNames(nm %in% x, nm)
}))
cbind(df[1], dc)
#   id   Red  Blue Green
# 1  1  TRUE FALSE FALSE
# 2  2  TRUE  TRUE FALSE
# 3  3 FALSE  TRUE  TRUE

更新:这是使用stringi包中的函数的更短,更有效的方法

mat <- vapply(nm, stringi::stri_detect_fixed, logical(3L), str = df$keywords)
cbind(df[1], mat)
#   id   Red  Blue Green
# 1  1  TRUE FALSE FALSE
# 2  2  TRUE  TRUE FALSE
# 3  3 FALSE  TRUE  TRUE

答案 3 :(得分:1)

dplyr的解决方案:

library(dplyr)
df %>%
  #just one mutate function really needed as below
  mutate(Red  = grepl('Red'  , df$keywords),
         Blue = grepl('Blue' , df$keywords),
         Green= grepl('Green', df$keywords)) %>%
  #select the columns you need 
  select(id, Red, Blue, Green)

输出:

  id   Red  Blue Green
1  1  TRUE FALSE FALSE
2  2  TRUE  TRUE FALSE
3  3 FALSE  TRUE  TRUE

如果你有很多变数,或者另一种选择:

keywords <- c('Red', 'Blue', 'Green')
#one lapply function
df2 <-do.call(data.frame, lapply(keywords, function(x) grepl(x, df$keywords)))
colnames(df2) <- keywords
df <- cbind(df[-2], df2)

输出:

> df
  id   Red  Blue Green
1  1  TRUE FALSE FALSE
2  2  TRUE  TRUE FALSE
3  3 FALSE  TRUE  TRUE

答案 4 :(得分:0)

我的&#34; splitstackshape&#34;中的cSplit_e函数包执行此操作(转换为1和0而不是TRUEFALSE s):

library(splitstackshape)
cSplit_e(d, "keywords", ",", type = "character", fill = 0)
#   id   keywords keywords_Blue keywords_Green keywords_Red
# 1  1        Red             0              0            1
# 2  2   Red,Blue             1              0            1
# 3  3 Green,Blue             1              1            0

如果要删除原始列,还有一个drop参数。