R:按 space 拆分数据框行,删除公共元素,将不等长的列放入新的 df

R: split data frame rows by space, remove common elements, put unequal length columns in new df

假设,我有 df 两行字符串,我需要按 space 拆分,unlist,然后在列表中找到反交叉和重用。我可以通过单独处理每一行来蛮力做到这一点。问题是可以有超过 2 行等。到目前为止,我的工作解决方案如下,但必须有一种不访问每一行的更简单的方法。谢谢!!

    df = structure(list(A = structure(1:2, .Label = c("R1", "R2"), class = "factor"), 
                        B = c("a b c d e f g o l", 
                              "b h i j k l m n o p q"
                        )), .Names = c("A", "B"), row.names = c(NA, -2L), class = "data.frame")

    dat1 = unlist(strsplit(df[1,2]," "))
    dat2 = unlist(strsplit(df[2,2]," "))

    f <- function (...) 
    {
      aux <- list(...)
      ind <- rep(1:length(aux), sapply(aux, length))
      x <- unlist(aux)
      boo <- !(duplicated(x) | duplicated(x, fromLast = T))
      split(x[boo], ind[boo])
    }

    excl = (f(dat1, dat2))
L <- list(excl[[1]],excl[[2]])

cfun <- function(L) {
  pad.na <- function(x,len) {
    c(x,rep("",len-length(x)))
  }
  maxlen <- max(sapply(L,length))
  print(maxlen)
  do.call(data.frame,lapply(L,pad.na,len=maxlen))
}

a = cfun(L)

我拥有的:

    A   B
1   Food    a b c d e f g
2   HABA    b h i j k l m n o p q

我得到的:

    c..a....c....d....e....f....g.......... c..h....i....j....k....m....n....p....q..
1   a   h
2   c   i
3   d   j
4   e   k
5   f   m
6   g   n
7       p
8       q

编辑:目标是消除所有列中的公共元素。 IE。如果“4”出现在第 1 行并且在其他任何地方都可以看到 - 删除。新测试集:

df1 = structure(list(A = structure(1:3, .Label = c("R1", "R2", "R3"
), class = "factor"), B = c("1 4 78 5 4 6 7 0", "2 3 76 8 2 1 8 0", 
"4 7 1 2")), .Names = c("A", "B"), row.names = c(NA, -3L), class = "data.frame")

建议代码的当前输出:

    a   b   c
1   4   2   4
2   78  3   7
3   5   76  2
4   4   8   NA
5   6   2   NA
6   7   8   NA
7   0   0   NA

2、4 和 7 不应该存在,因为它们出现在不止 1 列中。底线 - 输出应仅在任何列中包含唯一的 numbers/elements。谢谢!!

这是一种使用 base R 的方法,可以避免大量当前代码

## split column B on the space character
s <- strsplit(df$B, " ")
## find the intersection of all s
r <- Reduce(intersect, s)
## iterate over s, removing the intersection characters in r
l <- lapply(s, function(x) x[!x %in% r])
## reset the length of each vector in l to the length of the longest vector
## then create the new data frame
setNames(as.data.frame(lapply(l, "length<-", max(lengths(l)))), letters[seq_along(l)])
#      a b
# 1    a h
# 2    c i
# 3    d j
# 4    e k
# 5    f m
# 6    g n
# 7 <NA> p
# 8 <NA> q

我想这就是你拍摄的目的吧?

注意 lengths() 是 R 版本 3.2.0 基础包中的一个新函数,可以更快更有效地替代 sapply(x, length)一个列表。