2012-04-21 93 views

回答

5

正如@John所述,使用duplicated时出现问题。我会补充说,在与duplicated比较之前,将data.frame强制转换为相同的数据类型。在一个例子,这里是一个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 

注意,列c非常相似eb,和f,但不是因为不同类型的相同(字符与数字)。 @Jubbles建议的解决方案将忽略这些差异。

相反,在data.frame的列上使用identical函数似乎更合适。您可以比较使用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 

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

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" 

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

are.cols.identical <- function(col1,col2) isTRUE(all.equal((df[,col1],df[,col2])) 

编辑2:比聚类进行分组相同列的名称更有效的方法是

cut <- apply(identical.mat, 1, function(x)match(TRUE, x)) 
split(colnames(df), cut) 
+0

Upvote from me。感谢您提供比我更详尽的答案。 – Jubbles 2012-04-22 01:53:12

+0

我喜欢在这里使用集群。这里有更多潜在答案的空间,因为这个答案没有解决即使值基本相同也会出现的浮点值差异问题。 – John 2012-04-22 02:32:49

+0

从identical.mat中提取信息的另一种方法可能是...... which(identical.mat,arr.ind = TRUE)'(只有使用lower.tri()才会更好) – John 2012-04-22 02:35:49

2

如何转置数据帧并使用duplicated()

B <- as.data.frame(t(A)) 
dup1 <- duplicated(B) 
# if you want to identify all duplicated rows 
dup2 <- duplicated(B, fromLast = TRUE) 
dup_final <- dup1 * dup2 
saved_colnames <- colnames(A)[dup_final] 
+0

我需要保存列的名字... – 2012-04-21 13:07:12

+1

@大卫Kakauridze后使用:我认为我添加的最后一行应该注意这一点。 – Jubbles 2012-04-21 13:09:03

+1

duplicateated()命令会将每个值视为文本。在某些情况下某些值可能被认为是相等的,但不能被视为文本(甚至不是以其自然形式)。例如,许多0的值将不会如此表示(例如,tan(pi))。浮点数可能是一个严重的问题。对于提问者的情况可能没问题,但应该警告未来的读者,这不是一个通用的解决方案。(并没有一个通用的解决方案没有一个更复杂的功能) – John 2012-04-21 14:09:46

4

这个问题是非常类似于一个here,但与用相同的警告细微的差别。

我将在下面使用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" 

这仍然不会1.01区分再次建议,但是。

编辑

如由@flodel的意见建议,下面可以交替创建dfDig

+0

+1 - 很好,很简洁。我不知道'digest',谢谢你提出这个建议。 – flodel 2012-04-22 11:31:31

+1

使用'match'可能比'which'更快。这似乎工作:'分裂(colnames(df),vapply(dfDig,match,1L,dfDig))' – flodel 2012-04-22 11:46:33

+0

@ flodel,这是一个很好的建议。我会在上面添加它。 – BenBarnes 2012-04-22 12:23:06

相关问题