0

Aという名前のdata.frameが1つあり、5000列あります。この data.frame で互いに等しい列を見つけるにはどうすればよいですか。

4

3 に答える 3

6

@John が述べたように、使用には問題がありますduplicated。data.frame と比較する前に、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

columnは、columns 、、およびcに非常に似ていますが、タイプ (文字と数値) が異なるため同一ではないことに注意してください。@Jubbles によって提案された解決策は、これらの違いを無視します。 bef

identical代わりに、 data.frame の列で関数を使用する方が適切と思われます。を使用して、列を 2 つずつ比較できます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)
于 2012-04-21T15:45:38.800 に答える
6

この質問は、こちらの質問と非常によく似ていますが、微妙な違いはありますが、注意点は同じです。

次のように、を使用することを再度お勧めしdigest()ます (data.frame の @flodel と上記の非常に素晴らしい提案に感謝します)。

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.0ただし、これでもとを区別できません1

編集

@flodel のコメントで示唆されているように、作成後に以下を代わりに使用できます。dfDig

split(colnames(df), vapply(dfDig, match, 1L, dfDig))
于 2012-04-22T09:18:14.800 に答える
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]
于 2012-04-21T13:04:14.940 に答える