【问题标题】:R: Test for overlap of name values in dataframeR:测试数据框中名称值的重叠
【发布时间】:2020-03-11 19:31:15
【问题描述】:

我有一个填充了名称的数据框。

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

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

  1. "吉姆","德怀特","迈克尔","安迪","斯坦利","克里德"

  2. "吉姆","德怀特","安吉拉","帕姆","瑞恩","简"

  3. "Jim","Dwight","Angela","Pam","Creed","Ryan"

首先我们将第 3 行与第 1 行进行比较,发现名称重叠为 3,符合

然后我们将第 3 行与第 2 行进行比较,发现名称重叠为 5,它不符合

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

【问题讨论】:

  • 您应该发布dput( head(your_dataframe)),以便我们确定这些值是否是因子。然后我们可以确定第一步是否应该在尝试对相交值进行基于行的计数之前转换为字符。

标签: r string dataframe matching


【解决方案1】:

示例数据

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

【讨论】:

  • 曙光初现,我推翻了我的反对意见。我看到你的结果不是偶然的(以你的例子),我误解了它们是如何产生的。我还看到您创建示例的方法导致所有值都处于因子水平。但是,我怀疑该方法对于 OP 的数据集可能不会成功。
【解决方案2】:

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

对于data.frame:

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))
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 2023-03-19
    • 2018-12-21
    • 2019-01-10
    • 2022-01-03
    相关资源
    最近更新 更多