是否有可能在 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
在它上面。
我知道这个问题令人困惑,但我不知道如何更好地表述它。我有 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
在它上面。