考虑以下数据:
library(tibble)
key <- c("a", "b", "c", "d", "e")
tags <- c("A,B", "B", "A,E", "C,D", "")
data <- tibble(key, tags)
此处,key
可能表示书名,tags
可能是流派,或key
可能是电子邮件发件人,tags
可能表示收件人。必不可少的是,列tags
可以具有变量(可能为零)个不同的子串。
对于拆分固定数量的连接标签(例如数据),我可以使用tidyr::spread
,我可以使用字符串拆分来分隔tags
列本身,但如何将两者结合起来?
我希望转换的数据看起来像这样:
key A B C D E
a TRUE TRUE FALSE FALSE FALSE
b FALSE TRUE FALSE FALSE FALSE
c TRUE FALSE FALSE FALSE TRUE
d FALSE FALSE TRUE TRUE FALSE
e FALSE FALSE FALSE FALSE FALSE
我可以通过拆分tags
,确定唯一的子串并循环遍历每个子行并测试每行的tags
是否包含字符串,从而分几步完成此操作。但我更喜欢使用tidyverse 在管道中执行。
问题:如何将每个标记的可变数量的连接标记拆分为一列?
答案 0 :(得分:5)
这是一个基本的R替代方法:
# get unique values in tags
x <- unique(unlist(strsplit(df$tags, ",", fixed=TRUE)))
# check for existence in the tags column
res <- sapply(paste0("(^|.*,)", x, "(,.*|$)"), grepl, df$tags)
# add sensible dimension names
dimnames(res) <- list(df$key, x)
结果矩阵如下所示:
res
# A B E C D
#a TRUE TRUE FALSE FALSE FALSE
#b FALSE TRUE FALSE FALSE FALSE
#c TRUE FALSE TRUE FALSE FALSE
#d FALSE FALSE FALSE TRUE TRUE
#e FALSE FALSE FALSE FALSE FALSE
答案 1 :(得分:3)
来自 tidyr 的separate_rows
功能可以帮助您获得所需的位置。这会将tags
中的字符串拆分为单独的行而不是单独的列,这样就可以使用spread
。
要获取TRUE
/ FALSE
结果,我创建了一个包含所有TRUE
的新列作为值列,然后在FALSE
填充了spread
{1}}。最后,spread
将空白单元格保留为列名称,我通过select
删除了该名称。可能有更好的方法(可能转换为NA?)。
library(tidyr)
library(dplyr)
data %>%
separate_rows(tags) %>%
mutate(tagslog = TRUE) %>%
spread(tags, tagslog, fill = FALSE) %>%
select(-one_of(""))
key A B C D E
* <chr> <lgl> <lgl> <lgl> <lgl> <lgl>
1 a TRUE TRUE FALSE FALSE FALSE
2 b FALSE TRUE FALSE FALSE FALSE
3 c TRUE FALSE FALSE FALSE TRUE
4 d FALSE FALSE TRUE TRUE FALSE
5 e FALSE FALSE FALSE FALSE FALSE
您只需separate_rows
和table
几乎可以到达目的地,但我仍然需要删除额外的空白列。
data %>%
separate_rows(tags) %>%
with(., table(key, tags) == 1)
tags
key A B C D E
a FALSE TRUE TRUE FALSE FALSE FALSE
b FALSE FALSE TRUE FALSE FALSE FALSE
c FALSE TRUE FALSE FALSE FALSE TRUE
d FALSE FALSE FALSE TRUE TRUE FALSE
e TRUE FALSE FALSE FALSE FALSE FALSE
答案 2 :(得分:1)
第三个基础R方法是
currencyName : {type : String, required : true}
返回
# get named list splitting by commas
myList <- setNames(strsplit(tags, split=",", fixed=TRUE), key)
# get unique elements from list
colTemp <- sort(unique(unlist(myList)))
# check each list element for the unique elements, return matrix
myMat <- t(sapply(myList, function(i) colTemp %in% i))
# add column names
colnames(myMat) <- colTemp
答案 3 :(得分:0)
从docendo discimus方法,使用不同的粘贴功能方式
xx <- sort(unique(unlist(strsplit(data$tags,","))))
data1 <- sapply(paste(xx), grepl, data$tags)
data <- cbind(data[,1],data1)
key A B C D E
1 a TRUE TRUE FALSE FALSE FALSE
2 b FALSE TRUE FALSE FALSE FALSE
3 c TRUE FALSE FALSE FALSE TRUE
4 d FALSE FALSE TRUE TRUE FALSE
5 e FALSE FALSE FALSE FALSE FALSE