2012-04-21 71 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

相關問題