在一个data.frame中查找具有相同数据的列

Dav*_*dze -1 r dataframe

我有一个名为A的data.frame,其中有5000列.如何在此data.frame中找到彼此相等的列.

flo*_*del 5

正如@John所说,使用时存在问题duplicated.我想补充一点,转换data.frame会强制所有数据进入相同的数据类型,然后再进行比较duplicated.举个例子,这是一个data.frame:

df <- data.frame( a = LETTERS[1:3],
                  b = 1:3,
                  c = as.character(1:3),
                  d = LETTERS[1:3],
                  e = 1:3,
                  f = 1:3)
df
#   a b c d e f
# 1 A 1 1 A 1 1
# 2 B 2 2 B 2 2
# 3 C 3 3 C 3 3
Run Code Online (Sandbox Code Playgroud)

需要注意的是列c非常相似,列b,ef,但不会因为不同类型(字符与数字)的相同.@Jubbles建议的解决方案会忽略这些差异.

相反,identical在data.frame的列上使用该函数似乎更合适.您可以使用outer以下方法对列进行二乘比较:

are.cols.identical <- function(col1, col2) identical(df[,col1], df[,col2])
identical.mat      <- outer(colnames(df), colnames(df),
                            FUN = Vectorize(are.cols.identical))
identical.mat
# [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
# [1,]  TRUE FALSE FALSE  TRUE FALSE FALSE
# [2,] FALSE  TRUE FALSE FALSE  TRUE  TRUE
# [3,] FALSE FALSE  TRUE FALSE FALSE FALSE
# [4,]  TRUE FALSE FALSE  TRUE FALSE FALSE
# [5,] FALSE  TRUE FALSE FALSE  TRUE  TRUE
# [6,] FALSE  TRUE FALSE FALSE  TRUE  TRUE
Run Code Online (Sandbox Code Playgroud)

从这里,您可以使用群集来识别相同列的组(可能有更好的方法,所以如果您知道一个,请随意评论甚至编辑我的答案.)

library(cluster)
distances <- as.dist(!identical.mat)
tree      <- hclust(distances)
cut       <- cutree(tree, h = 0.5)
cut
# [1] 1 2 3 1 2 2

split(colnames(df), cut)
# $`1`
# [1] "a" "d"
# 
# $`2`
# [1] "b" "e" "f"
# 
# $`3`
# [1] "c"
Run Code Online (Sandbox Code Playgroud)

编辑1:忽略浮点值的差异,可以使用

are.cols.identical <- function(col1,col2) isTRUE(all.equal((df[,col1],df[,col2]))
Run Code Online (Sandbox Code Playgroud)

编辑2:一种比聚类更有效的方法,用于对相同列的名称进行分组

cut <- apply(identical.mat, 1, function(x)match(TRUE, x))
split(colnames(df), cut)
Run Code Online (Sandbox Code Playgroud)


Ben*_*nes 5

这个问题与这里的问题非常相似,但有一些细微的差别,同样需要注意.

我会再次建议使用digest(),如下所示(感谢@flodel的data.frame和上面的一个非常好的建议)

df <- data.frame( a = LETTERS[1:3],
  b = 1:3,
  c = as.character(1:3),
  d = LETTERS[1:3],
  e = 1:3,
  f = 1:3)

dfDig <- sapply(df, digest)

ansL <- lapply(seq_along(dfDig), function(x) names(which(dfDig == dfDig[x])))

unique(ansL)

# [[1]]
# [1] "a" "d"

# [[2]]
# [1] "b" "e" "f"

# [[3]]
# [1] "c"
Run Code Online (Sandbox Code Playgroud)

但是,这仍然无法区分1.01.

编辑

正如@flodel的评论中所建议的,创建后可以使用以下选项 dfDig

split(colnames(df), vapply(dfDig, match, 1L, dfDig))
Run Code Online (Sandbox Code Playgroud)