jmi*_*738 4 r strsplit set-difference
我有2个因子列,我想创建第三列,它告诉我第二列是什么,第一列没有.它与这篇文章非常相似,但是我从df使用setdiff()函数到使用函数时遇到了麻烦.
例如:
library(dplyr)
y1 <- c("a.b.","a.","b.c.d.")
y2 <- c("a.b.c.","a.b.","b.c.d.")
df <- data.frame(y1,y2)
Run Code Online (Sandbox Code Playgroud)
列y1有a.b.和列y2有a.b.c..我想要一个三分之一的列返回c.或只是c.
> df
y1 y2 col3
1 a.b. a.b.c. c.
2 a. a.b. b.
3 b.c.d. b.c.d.
Run Code Online (Sandbox Code Playgroud)
我认为这是应该的组合strsplit和setdiff,但我不能得到它的工作.
我试图将其转换factor为character,然后我尝试应用于strsplit()结果,但输出对我来说似乎很奇怪.它似乎在列表中创建了一个列表,这使得很难传递给它setdiff()
#convert factor to character
df <- df %>% mutate_if(is.factor, as.character)
lapply(df$y1,function(x)(strsplit(x,split = "[.]")))
> lapply(df$y1,function(x)(strsplit(x,split = "[.]")))
[[1]]
[[1]][[1]]
[1] "a" "b"
[[2]]
[[2]][[1]]
[1] "a"
[[3]]
[[3]][[1]]
[1] "b" "c" "d"
Run Code Online (Sandbox Code Playgroud)
更新
当差异超过1个字符时出现问题,它创建了一个额外的行.为了克服这个问题,我们将paste所有元素结合在一 这也使我们免于unlist步骤.
df$col3 <- mapply(function(x, y) paste0(setdiff(y, x), collapse = ""),
strsplit(as.character(df$y1), "\\."), strsplit(as.character(df$y2), "\\."))
Run Code Online (Sandbox Code Playgroud)
原始答案
我们可以mapply在"."上使用和拆分两列.使用strsplit然后使用它们之间的差异setdiff.
df$col3 <- mapply(function(x, y) setdiff(y, x),
strsplit(as.character(df$y1), "\\."), strsplit(as.character(df$y2), "\\."))
df
# y1 y2 col3
#1 a.b. a.b.c. c
#2 a. a.b. b
#3 b.c.d. b.c.d.
Run Code Online (Sandbox Code Playgroud)
如果我们不想col3作为列表,我们可以unlist,但是,如果我们从中unlist删除它的一个问题character(0).为了保留该值,我们需要对其进行额外检查.取自这里.
unlist(lapply(df$col3,function(x) if(identical(x,character(0))) ' ' else x))
#[1] "c" "b" " "
Run Code Online (Sandbox Code Playgroud)