【问题标题】:Finding all the possible combinations based on the presence or not of data in the rows根据行中数据的存在与否查找所有可能的组合
【发布时间】:2023-11-09 10:21:02
【问题描述】:

我正在处理一个大型数据框,其中在称为离子分数的列中有许多空行 (NA)。基本上,这个分数是对某些蛋白质的识别。

我的数据框的大体结构是:

N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 | 
1 | 4322      |  5             | 5          | 5          | 
2 | 2344      |  5             | NA         | 5          | 
3 | 2341      |  NA            | 5          | NA         |   
4 | 2346      |  NA            | NA         | 5          |   
5 | 2346      |  5             | NA         | NA         |  
6 | 2348      |  NA            |  5         | 5          |  
7 | 2349      |  5             | 5          | NA         | 

我想要的是这样的:

df1:
N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 | 
1 | 4322      |  5             | 5          | 5          | 

df2:
N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 |
2 | 2349      |  5             | 5          | NA         | 

df3: 
N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 |
3 | 2344      |  5             | NA         | 5          |  

df4:
N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 |
5 | 2347      |  NA            | NA         | 5          |  
.
. 
.

等等,考虑到所有可能的组合。

在获取包含所有可能组合的数据表的情况下,一个更具说明性的示例如下:

N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 | 
1 | 4322      |  5             | 5          | 5          | 
2 | 2349      |  5             | 5          | NA         | 
3 | 2344      |  5             | NA         | 5          |   
4 | 2348      |  NA            | 5          | 5          | 
5 | 2347      |  NA            | NA         | 5          | 
6 | 2341      |  NA            | 5          | NA         | 
7 | 2349      |  5             | NA         | NA         |  

为了更清楚,通过这种方式,我可以看到哪些是三个共同的,两个是共同的,哪些只在一个样本中。

我认为最好的方法是在 R 中使用组合。 然后尝试对列进行过滤、排序和分组。

首先我使用它来了解可能有多少种组合

#Where N is the number of combinations, in this case 3. 
Combination_table <- data.frame(expand.grid(rep(list(0:1), 19))) 
#invert row order
Combination_table <- Combination_table[-nrow(Combination_table), ] 

然后按照组合过滤并创建一个新的数据框:

df1 <- data.frame(Proteins[!is.na(Proteins$Ion Score) &
                               !is.na(Proteins$Ion Score2) &
                               !is.na(Proteins$Ion Score3), ])
df2 <- data.frame(Proteins[!is.na(Proteins$Ion Score) &
                               is.na(Proteins$Ion Score2) &
                               !is.na(Proteins$Ion Score3), ])
df3 <- data.frame(Proteins[!is.na(Proteins$Ion Score) &
                               !is.na(Proteins$Ion Score2) &
                               is.na(Proteins$Ion Score3), ])
df4 <- data.frame(Proteins[is.na(Proteins$Ion Score) &
                               is.na(Proteins$Ion Score2) &
                               !is.na(Proteins$Ion Score3), ])
.
.
.

等等

这很好用,问题是当我有很多离子分数列时。例如,9 个 Ion Score 列 = 512 种可能的组合。

您知道另一种方法吗?

示例数据集:

Proteins <- data.frame(N = c(1, 2, 3, 4), Accession = c(4322, 
    222, 2344, 2341), `Ion Score1` = c(5, 5, "NA", "NA"), `Ion Score2` = c(5, 
    "NA", 5, 5), `Ion Score3` = c(5, 5, "NA", 5))

编辑:

N | Accession |  Ion Score1    | Ion Score2 | Ion Score3 | 
1 | 4322      |  3             | 51         | 12          | 
2 | 4533      |  7             | NA         | 87          | 
3 | 4125      |  NA            | 9          | NA          |  
4 | 8964      |  NA            | 9          | NA          |  
5 | 5454      |  NA            | 10         | NA         |  
6 | 9871      |  6             | 5          | NA          |  
7 | 7562      |  NA            | 5          | NA          |   
8 | 7894      |  8             | NA         | 5           |   
9 | 0189      |  5             | NA         | NA          |  
10| 8746      |  NA            |  45        | 54          |  
11| 8746      |  5             | 23          | NA         | 

例子:

Proteins <- data.frame(N = c(1, 2, 3, 4,5,6,7,8,9,10,11), Accession = c(4322,222, 2344, 2341,6598,98974,7889,78798,1212,4566,1148), `Ion Score1` = c(3, 7, "NA", "NA","NA",6,"NA",8,5,"NA",5), `Ion Score2` = c(51, "NA",9,9,10,5,5,"NA","NA",45, 23), `Ion Score3` = c(12,87,"NA","NA","NA","NA","NA", 5, "NA", 54,"NA"))

【问题讨论】:

  • 什么组合?这不是很清楚。请同时发布预期结果
  • @Sotos 组合不重复。我的意思是例如:有这个字母,A,B,C......找到可能的组合。所以,这应该是:ABC、AB、AC 和 BC。这就是我在这个示例中所做的,比较 3 个示例之间的所有可能组合。
  • 不,我知道组合是什么 :) 我问的是你在组合什么
  • @Sotos 我正在结合 Ion Score 的数据。该数字表示样品中是否存在蛋白质。如果 Ion Score 列中有数字,则表示存在蛋白质。如果没有 (NA),则表示没有蛋白质。
  • @Sotos 例如,在第一行你可以看到 5 | 5 | 5. 这意味着这三个例子中有一个蛋白质。在下一行你可以看到: 5 | 5 |不适用。这意味着示例 1 和示例 2 中存在蛋白质,但示例 3 中没有。

标签: r combinations multiple-columns


【解决方案1】:

我认为您正在寻找expand.grid(),您可以使用它来制作所有组合的查找表(我在这里称之为x2)。然后,我遍历所有组合(即nrow(x2))并提取数据框的匹配行。

Proteins <- data.frame(N = c(1, 2, 3, 4), Accession = c(4322, 
    222, 2344, 2341), `Ion Score1` = c(5, 5, NA, NA), `Ion Score2` = c(5, 
    NA, 5, 5), `Ion Score3` = c(5, 5, NA, 5), stringsAsFactors = F)

cols <- 3  # Number of 'Ion Score' columns

# make a grid of all combinations
x1 <- do.call(rep, args = list(list(c(1, NA)), cols))
x2 <- as.matrix(expand.grid(x1))

head(x2)
#>      Var1 Var2 Var3
#> [1,]    1    1    1
#> [2,]   NA    1    1
#> [3,]    1   NA    1
#> [4,]   NA   NA    1
#> [5,]    1    1   NA
#> [6,]   NA    1   NA

for (ii in seq_len(nrow(x2))) {
    idx <- apply(Proteins[, 3:5], 1, function(x) {
        isTRUE(all.equal(is.na(x), is.na(x2[ii, ]), check.attributes = FALSE, use.names = FALSE))
    })
    if (any(idx))
        assign(paste0("df", ii), Proteins[idx, ])
}

df1
#>   N Accession Ion.Score1 Ion.Score2 Ion.Score3
#> 1 1      4322          5          5          5
df2
#>   N Accession Ion.Score1 Ion.Score2 Ion.Score3
#> 4 4      2341         NA          5          5
df3
#>   N Accession Ion.Score1 Ion.Score2 Ion.Score3
#> 2 2       222          5         NA          5
df6
#>   N Accession Ion.Score1 Ion.Score2 Ion.Score3
#> 3 3      2344         NA          5         NA

请注意,我更改了 Proteins 数据集并创建了数字变量,而不是您的示例中的字符串因子。

【讨论】:

  • 感谢您的回答。我可以将您的示例与数字或字符串一起使用吗?数字 5 只是一个示例,列数可以多于或少于此示例。事实上,我正在尝试将您的答案应用到 19 列的数据框中。
  • 您能否在 (a) 可能出现哪些值和 (b) 应以类似方式处理哪些值时更加明确?例如,5|3|NA 是否应该像 5|5|NA 一样对待,或者应该是不同的组。列数和字符串与数字的对比应该不是问题。
  • a) 任何值都可能出现,这并不重要。基本上,数字表示样品中是否存在蛋白质。如果 Ion Score 列中有数字,则表示存在蛋白质。如果没有数字 (NA),这意味着没有蛋白质。 b) 是的,应该同样对待。一个数字或多或少类似于 TRUE,而 NA 在布尔方式中类似于 FALSE。
【解决方案2】:

这是使用split 函数的解决方案。为了找到离子分数的所有组合,我连接了NA's 的索引以创建一个唯一的可能性字符串。结果是一个列表,对我来说这是存储结果以供下游分析的更好方法。

df <- split(Proteins, drop = T, 
           f = list(apply(Proteins[, -c(1:2)], 1, 
                                    function(x) paste(which(is.na(x)),
                                                      collapse = "") )))

# [[1]]
# N Accession Ion.Score1 Ion.Score2 Ion.Score3
# 1 1      4322          5          5          5
# 
# $`1`
# N Accession Ion.Score1 Ion.Score2 Ion.Score3
# 4 4      2341         NA          5          5
# 
# $`13`
# N Accession Ion.Score1 Ion.Score2 Ion.Score3
# 3 3      2344         NA          5         NA
# 
# $`2`
# N Accession Ion.Score1 Ion.Score2 Ion.Score3
# 2 2       222          5         NA          5

【讨论】:

  • 我不明白你的意思。在该列表中,我怎样才能找到那些没有 NA 的人和那些有一个或多个 NA 的人?我需要将这些结果导出到 Excel。
  • 根据您的帖子,您希望根据缺少蛋白质的Ion Score 拆分数据(我编辑了我的答案以删除蛋白质 ID 上的拆分)。根据names(df),您可以确定蛋白质缺失的次数以及缺失的离子分数。如果您希望根据丢失的次数拆分数据,那么最好根据每个蛋白质的 NAs 的总和来拆分数据。
  • 是的,但我可以缺少一个以上的离子分数。我认为列表应该是列表的列表。我用我的意思的一个例子编辑了我的问题。
  • 请提供一个您期望输出的示例。我认为...鉴于此条目(来自您编辑的帖子)3 | 4125 | NA | 9 | NA | ,您希望它显示三次:缺少 Ion Score1、Ion Score3 和两者(Ion Score1 和 Ion Score3)的列表。对吗?
最近更新 更多