R - 数据帧中2组之间的差异

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)

y1a.b.和列y2a.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)

我认为这是应该的组合strsplitsetdiff,但我不能得到它的工作.

我试图将其转换factorcharacter,然后我尝试应用于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)

Ron*_*hah 5

更新

当差异超过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)