【问题标题】:Loop "identical" function over all columns of dataframe在数据框的所有列上循环“相同”函数
【发布时间】:2018-12-19 02:45:32
【问题描述】:

给定一个数据框,例如:

df <- data.frame(A.a = c("a","b","c"),
                 A.b = c("a","b","c"),
                 A.c = c("aa","bb","cc"),
                 B.a = c("w","x","y"))

我想在数据框的所有列上循环“相同”函数。 到目前为止,我已经能够创建这个函数:

loop.col.identical <- function(df){
    for i in colnames(df){
        cat(identical(df[[i]], df[[i]]))
    }
}

但它只是将每一列与它们自己进行比较,为所有内容输出 TRUE。我想确定 cols A.a 和 A.b 是相同的,但 A.c 是不同的,因为它也应该是相同的。 请注意,这是一个小例子,我的真实数据有更多的列和行。

P.d:抱歉,我在手机上

【问题讨论】:

  • 你的预期输出是什么?
  • 3 列的 df,列 1 列 2 和第三列,列 1 和列 2 之间的逻辑标识声明

标签: r


【解决方案1】:

如果我正确理解您的问题,您希望在数据框中的各个列之间进行成对匹配。

expand.grid(x=colnames(df), y=colnames(df)) %>% 
  mutate(match = map2_lgl(x,y, ~identical(df[[.x]],df[[.y]]))) %>%
  spread(x,match)

这是输出:

    y   A.a   A.b   A.c   B.a
1 A.a  TRUE  TRUE FALSE FALSE
2 A.b  TRUE  TRUE FALSE FALSE
3 A.c FALSE FALSE  TRUE FALSE
4 B.a FALSE FALSE FALSE  TRUE

根据您的需要,您可以忽略最后一个spread 操作。

【讨论】:

  • 与此输出等效的 Base R 为 outer(df, df, FUN=Vectorize(identical))
  • 如果我想将布尔值转换为数字,然后创建一个树状图,将此输出作为距离矩阵传递,这很有用,这实际上是我解决问题的第一种方法,使用“stringdist”,但它与大型数据集崩溃。感谢您的反馈。
  • 在比较来自不同数据框的列时,这个实际上有很大帮助
【解决方案2】:

这是一个想法。

首先,创建一个新的数据框,其中包含两列显示要比较的列名。请注意,我删除了具有相同名称和相同比较的那个。

dat <- expand.grid(x = names(df), y = names(df))
dat <- dat[dat$x != dat$y, ]
dat <- data.frame(t(apply(dat, 1, sort)), stringsAsFactors = FALSE)
dat <- dat[!duplicated(dat), ]
names(dat) <- c("x", "y")

之后,我们可以使用mapply循环组合并生成如下输出。

dat$Result <- mapply(function(x, y){
  identical(df[[x]], df[[y]])
}, dat$x, dat$y, SIMPLIFY = TRUE)

dat
#      x   y Result
# 2  A.a A.b   TRUE
# 3  A.a A.c  FALSE
# 4  A.a B.a  FALSE
# 7  A.b A.c  FALSE
# 8  A.b B.a  FALSE
# 12 A.c B.a  FALSE

更新

正如@thelatemail 所述,combn 函数使第一部分变得简单。

dat <- data.frame(t(combn(names(df), 2)), stringsAsFactors = FALSE)

dat$Result <- mapply(function(x, y){
  identical(df[[x]], df[[y]])
}, dat$X1, dat$X2, SIMPLIFY = TRUE)

dat
#    X1  X2 Result
# 1 A.a A.b   TRUE
# 2 A.a A.c  FALSE
# 3 A.a B.a  FALSE
# 4 A.b A.c  FALSE
# 5 A.b B.a  FALSE
# 6 A.c B.a  FALSE

【讨论】:

  • combn 可能会让第一部分变得更简单,例如combn(names(df), 2) 甚至combn(df, 2, FUN=function(x) identical(x[[1]], x[[2]]) ) 以进一步推动它。
  • @thelatemail 感谢您对combn 的评论。感人的!我已根据您的评论更新了我的帖子。
  • 你可以通过传递combn 一个函数并简化为一个数据框来实现它作为一个单行:dplyr::bind_rows(combn(df, 2, function(x) list(v1 = names(x)[1], v2 = names(x)[2], identical = identical(x[[1]], x[[2]])), simplify = FALSE))
  • 我根据您的反馈创建了这个函数:loop.col.identical&lt;-function(df){ dat &lt;- data.frame(t(combn(names(df), 2)), stringsAsFactors = FALSE) dat$Result &lt;- mapply(function(x, y){ identical(df[[x]], df[[y]]) }, dat$X1, dat$X2, SIMPLIFY = TRUE) return(dat) },然后过滤了实际重复的列:consult.df&lt;-function(df,dfcol,q=TRUE){ for(i in q) query.result&lt;-df[ grep(i, dfcol), ] return(query.result) }
猜你喜欢
  • 2020-01-06
  • 2021-11-07
  • 2021-06-19
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 2015-08-16
  • 2021-06-28
  • 1970-01-01
相关资源
最近更新 更多