R:测试数据帧中名称值的重叠



我有一个充满名称的数据帧。

对于数据帧中的给定行,我想将该行与df中其上方的每一行进行比较,并确定每一行的匹配名称数是否小于或等于4。

玩具示例,其中第3行是感兴趣的行

  1. "Jim"、"Dwight"、"Michael"、"Andy"、"Stanley"、"Creed">

  2. "Jim"、"Dwight"、"Angela"、"Pam"、"Ryan"、"Jan">

  3. "Jim"、"Dwight"、"Angela"、"Pam"、"Creed"、"Ryan"<---感兴趣行

因此,首先我们将第3行与第1行进行比较,发现名称重叠为3,满足<=4个标准。

然后,我们将第3行与第2行进行比较,发现名称重叠为5,这使&lt4个标准,最终返回<上面每行4个。

现在我正在使用for循环进行此操作,但速度对于我使用的数据帧大小来说太慢了。

示例数据

df <- as.data.frame(rbind(
c("Jim","Dwight","Michael","Andy","Stanley","Creed"),
c("Jim","Dwight","Angela","Pam","Ryan","Jan"),
c("Jim","Dwight","Angela","Pam","Creed","Ryan")
), stringsAsFactors = FALSE)
df
#    V1     V2      V3   V4      V5    V6
# 1 Jim Dwight Michael Andy Stanley Creed
# 2 Jim Dwight  Angela  Pam    Ryan   Jan
# 3 Jim Dwight  Angela  Pam   Creed  Ryan

操作和输出(用%in%rowSums巧妙地越过列(

out_lgl <- rowSums(sapply(df, '%in%', unlist(df[3,]))) <= 4
out_lgl
# [1]  TRUE FALSE FALSE
which(out_lgl)
# [1] 1

解释:

对于每一列,将每个元素与第三行(向量unlist(df[3,])(进行比较。如果存在匹配,则输出是具有与dfTRUE相同维度的逻辑值的矩阵。

sapply(df, '%in%', unlist(df[3,]))
#        V1   V2    V3    V4    V5    V6
# [1,] TRUE TRUE FALSE FALSE FALSE  TRUE
# [2,] TRUE TRUE  TRUE  TRUE  TRUE FALSE
# [3,] TRUE TRUE  TRUE  TRUE  TRUE  TRUE

然后我们可以对TRUEs求和,以查看每行的匹配数量

rowSums(sapply(df, '%in%', unlist(df[3,])))
# [1] 3 5 6

编辑:

我已经在上面的df的创建中添加了stringsAsFactors = FALSE选项。然而,据我所知,无论是比较不同级别或不同特征的因素,%in%的输出都是相同的,所以我不认为这会以任何方式改变结果。参见以下示例

x <- c('b', 'c', 'z')
y <- c('a', 'b', 'g')
all.equal(x %in% y, factor(x) %in% factor(y))
# [1] TRUE

类似于IceCreamToucan的解决方案,但适用于任何行。

对于数据帧:

df <- as.data.frame(rbind(
c("Jim","Dwight","Michael","Andy","Stanley","Creed"),
c("Jim","Dwight","Angela","Pam","Ryan","Jan"),
c("Jim","Dwight","Angela","Pam","Creed","Ryan")
)

对于任何行号i:

f <- function(i) {
if(i == 1) return(T)
r <- vapply(df[1:(i-1),], '%in%', unlist(df[i,]), FUN.VALUE = logical(i-1))
out_lgl <- rowSums(as.matrix(r)) <= 4
return(all(out_lgl))
}

最新更新