Aという名前のdata.frameが1つあり、5000列あります。この data.frame で互いに等しい列を見つけるにはどうすればよいですか。
3 に答える
@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 によって提案された解決策は、これらの違いを無視します。 b
e
f
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)
この質問は、こちらの質問と非常によく似ていますが、微妙な違いはありますが、注意点は同じです。
次のように、を使用することを再度お勧めし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))
データフレームを転置して使用するのは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]