是否有可能在 R 中合并 2 个数据帧,只保留唯一结果,其中一列作为保留结果的依赖项

Is there a possibility to merge 2 dataframes in R, keeping only unique results with one of the columns as the dependency for which results are kept

我知道这个问题令人困惑,但我不知道如何更好地表述它。我有 11 个包含格式为

的 GOTerm IDS 的 xls 列表
ID   Category   Colour

这些列表总共包含大约 130,000 个 IDS,但是,其中只有 26,000 个是唯一的。

我按类别建立了 11 个列表的排名。我现在需要的是一种将列表 11 与列表 10 合并的方法,对于两个列表中的任何 ID,我想保留具有较低类别编号(在此示例中为类别 10)和匹配颜色的 ID。

我最好在一个脚本/所有列表的组合代码行中执行此操作。

例子

列表 11

ID 类别 颜色
1 类别 11 红色
2 类别 11 红色
3 类别 11 红色

列表 10

ID 类别 颜色
1 类别 10 蓝色
2 类别 10 蓝色
4 类别 10 蓝色

我理想的合并结果如下所示:

ID 类别 颜色
1 类别 10 蓝色
2 类别 10 蓝色
3 类别 11 红色
4 类别 10 蓝色

然后对于新列表与列表 9,结果与列表 8 等相同

这是您的问题的 data.table 解决方法。代码的功能解释在代码的注释中。

在此解决方案中,没有合并不同的表。相反,它们被行绑定在一起,并且每个 ID 只保留最先出现的行。

我不知道你在 excel 中是如何阅读的,但是如果你在 excel 中使用类似 L <- lapply(myexcelfiles, readxl::read_excel) 的方式阅读,那么你的 excel文件已经在列表中,您可以跳过下面的某些行并从行 DT <- rbindlist(L, id = "ListId").

开始
library(data.table)
# Sample data
List11 <- fread("ID     Category    colour
1   Category11  red
2   Category11  red
3   Category11  red")
List10 <- fread("ID     Category    colour
1   Category10  blue
2   Category10  blue
4   Category10  blue")

# Add the items (in order!) to a list
L <- list(List10, List11)
# Put the list in one large data.table
# Get a ListId from the position in the list
DT <- rbindlist(L, id = "ListId")
#    ListId ID   Category colour
# 1:      1  1 Category10   blue
# 2:      1  2 Category10   blue
# 3:      1  4 Category10   blue
# 4:      2  1 Category11    red
# 5:      2  2 Category11    red
# 6:      2  3 Category11    red
# Only keep rows with the minimum ListId by ID
# and drop the ListId column afterward and order on ID
final <- setorder(DT[ , .SD[which.min(ListId)], by = ID][, ListId := NULL], ID)
#    ID   Category colour
# 1:  1 Category10   blue
# 2:  2 Category10   blue
# 3:  3 Category11    red
# 4:  4 Category10   blue

让我分享这个示例,它应该让您了解使用基本 R 的步骤。

首先,让我们创建这两个数据框。 (A list 在 R 中有所不同。)

list11 <- data.frame(id = c(1, 2, 3),
                     category = "Category11",
                     colour = "red")
list10 <- data.frame(id = c(1, 2, 4),
                     category = "Category10",
                     colour = "blue")

这导致:

> list11
  id   category colour
1  1 Category11    red
2  2 Category11    red
3  3 Category11    red
> list10
  id   category colour
1  1 Category10   blue
2  2 Category10   blue
3  4 Category10   blue

接下来,您可以通过 ID 连接两个数据框:

joined <- merge(x = list10, y = list11, by = "id", all = TRUE)

这会给你:

> joined
  id category.x colour.x category.y colour.y
1  1 Category10     blue Category11      red
2  2 Category10     blue Category11      red
3  3       <NA>     <NA> Category11      red
4  4 Category10     blue       <NA>     <NA>

我们的想法是获取 x 列中存在的所有内容。只有当什么都没有时 (= <NA>) 我们才会检查 y 列。这就是我们使用 is.na() 函数所做的:

new10 <- joined[!is.na(joined$category.x), c("id", "category.x", "colour.x")]
new11 <- joined[is.na(joined$category.x), c("id", "category.y", "colour.y")]
> new10
  id category.x colour.x
1  1 Category10     blue
2  2 Category10     blue
4  4 Category10     blue
> new11
  id category.y colour.y
3  3 Category11      red

上面的 merge 函数给了我们新的列名,所以我们必须将它们设置回去:

colnames(new10) <- c("id", "category", "colour")
colnames(new11) <- c("id", "category", "colour")

现在两个数据框都有相同的列名,我们可以使用以下方法再次将它们粘在一起:

> final <- rbind(new10, new11)
> final
  id   category colour
1  1 Category10   blue
2  2 Category10   blue
4  4 Category10   blue
3  3 Category11    red

最后我们可以排序了,如果我们想这样做的话:

> final <- final[order(final$id), ]
> final
  id   category colour
1  1 Category10   blue
2  2 Category10   blue
3  3 Category11    red
4  4 Category10   blue

要处理所有 XLS,您可以围绕它创建一个循环或使用数据帧列表并 apply 在它上面。