簡體   English   中英

根據 R 中的逐行列相似性修剪 dataframe

[英]Prune a dataframe based on row-wise column similarity in R

我有一個非常大的 dataframe 基因組位點,其基因型得分為 0、1 或 2。這是我認為解決問題的一個非常小的樣本:

x1  x2  x3  x4
0   0   1   0
0   0   1   0
1   1   2   1
1   1   1   1
2   2   0   1
2   2   1   2

基因座 x1 和 x2 相同,而 x4 高度相似。 我希望實現的是創建一個 function,或使用已經存在的一個,為我的每個位點按行分配相似性分數,然后根據我設置的閾值相似性修剪數據集。

例如,如果我將閾值設置為 1 (100%),它只會修剪 x1 和 x2,因為它們是重復的——我知道該怎么做。 但是,如果我將閾值設置為 0.8,即相似度為 80%,那么除了 x1 和 x2 之外,它還會修剪 x4。

重要的是 function 作用於逐行相似性,而不只是比較具有相似分布的 0、1 和 2 的列。

以下是我將如何處理這個問題。

首先,獲取列名的所有唯一配對的列表:

pairs <- expand.grid(names(df), names(df))
pairs <- pairs[lower.tri(replicate(length(df), names(df))),]

pairs
#>    Var1 Var2
#> 2    x2   x1
#> 3    x3   x1
#> 4    x4   x1
#> 7    x3   x2
#> 8    x4   x2
#> 12   x4   x3

現在遍歷它以比較原始數據集中每對唯一列中相同行的比例。 這為每個列對提供了 0 到 1 之間的相似性分數:

pairs$similarity <- apply(pairs, 1, function(x) sum(df[x[1]] == df[x[2]])/nrow(df))

pairs
#>    Var1 Var2 similarity
#> 2    x2   x1  1.0000000
#> 3    x3   x1  0.1666667
#> 4    x4   x1  0.8333333
#> 7    x3   x2  0.1666667
#> 8    x4   x2  0.8333333
#> 12   x4   x3  0.1666667

現在刪除此列表中相似度得分低於您選擇的閾值的所有行(我們將在此處設為 0.8)

pairs <- pairs[which(pairs$similarity > 0.8),]

pairs
#>   Var1 Var2 similarity
#> 2   x2   x1  1.0000000
#> 4   x4   x1  0.8333333
#> 8   x4   x2  0.8333333

現在我們提取Var1Var2中的所有唯一列名稱,因為這些列與至少一個其他列相似:

keep_cols <- as.character(sort(unique(c(pairs$Var1, pairs$Var2))))
#> [1] "x1" "x2" "x4"

我們使用它對原始數據框進行子集化以獲得我們想要的結果:

df[match(keep_cols, names(df))]
#>   x1 x2 x4
#> 1  0  0  0
#> 2  0  0  0
#> 3  1  1  1
#> 4  1  1  1
#> 5  2  2  1
#> 6  2  2  2

當然,您可以將所有這些都放在 function 中,以便更輕松地調整閾值並迭代應用:

remove_dissimilar <- function(df, threshold = 0.8) {
  
  pairs <- expand.grid(names(df), names(df))
  pairs <- pairs[lower.tri(replicate(length(df), names(df))),]
  pairs$similarity <- apply(pairs, 1, function(x) {
    sum(df[x[1]] == df[x[2]])/nrow(df)})
  pairs <- pairs[which(pairs$similarity > threshold),]
  keep_cols <- as.character(sort(unique(c(pairs$Var1, pairs$Var2))))
  df[match(keep_cols, names(df))]
}

所以現在你可以這樣做:

remove_dissimilar(df, 0.8)
#>   x1 x2 x4
#> 1  0  0  0
#> 2  0  0  0
#> 3  1  1  1
#> 4  1  1  1
#> 5  2  2  1
#> 6  2  2  2

remove_dissimilar(df, 0.9)
#>   x1 x2
#> 1  0  0
#> 2  0  0
#> 3  1  1
#> 4  1  1
#> 5  2  2
#> 6  2  2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM