R:删除重复的名称列,同时保持每个位置的最大值
R: remove duplicate by name columns while keeping the max value per every position
到 2000 年,我有一个很大的 table 5000,其值如下。
我需要删除具有相同名称的列,同时保留列中每个位置的最大值(对于所有重复项)。
我卡住了..我有一个类似的代码,用于按行名删除重复项
x <- setDT(x)[, lapply(.SD, max), cName]
但我不知道如何使用相同的技巧,只能按列
prot1 prot1 prot1 prot2 prot3
0.889618286 0.907433399 0.085730039 0.010259207 0.01203583
0.766053072 0.061778787 0.193634896 0.387856898 0.029151237
0.399227213 0.980691544 0.30179994 0.768697098 0.749744349
0.089657475 0.353170832 0.85146464 0.580683125 0.606756472
0.341599883 0.790159839 0.653031942 0.011711575 0.569486433
0.627587607 0.363081942 0.628312001 0.137380824 0.535160381
所以清理后的版本是
prot1 prot2 prot3
0.907433399 0.010259207 0.01203583
0.766053072 0.387856898 0.029151237
0.980691544 0.768697098 0.749744349
0.85146464 0.580683125 0.606756472
0.790159839 0.011711575 0.569486433
0.628312001 0.137380824 0.535160381
在 base R
中,我们可以使用 'x' 的唯一列创建一个新数据集 ('x1')。按列名称拆分 'prot' 列的序列,使用该索引对 'x' 进行子集化,使用 pmax
获取每行的 max
值,并在列表中分配输出到 'x1'.
的 'prot' 列
x1 <- x[unique(colnames(x))]
x1[-1] <- lapply(split(2:ncol(x), colnames(x)[-1]),
function(i) do.call(pmax, x[i]))
x1
# cName prot1 prot2 prot3
#1 c1 0.9074334 0.01025921 0.01203583
#2 c2 0.7660531 0.38785690 0.02915124
#3 c3 0.9806915 0.76869710 0.74974435
#4 c4 0.8514646 0.58068312 0.60675647
#5 c5 0.7901598 0.01171158 0.56948643
#6 c6 0.6283120 0.13738082 0.53516038
或者使用data.table
,我们可以得到向量中唯一列名的索引('nm1'),创建一个'data.table',列数等于'nm1' 和与原始数据集相同的行数 ('dt1')。将 data.frame
转换为 data.table
(setDT
)。使用 for
循环,我们可以 set
'dt1' 的每一列中的值作为 'x' 中每个唯一列名称的行的最大值(do.call(pmax,
).
library(data.table)
nm1 <- unique(colnames(x)[-1])
dt1 <- as.data.table(matrix(NA, ncol=length(nm1), nrow=nrow(x),
dimnames=list(NULL, nm1)))
setDT(x)
for(j in seq_along(dt1)){
set(dt1, i=NULL, j=j, value= do.call(pmax,x[,colnames(x) %chin%
nm1[j], with=FALSE]))
}
dt1
# prot1 prot2 prot3
#1: 0.9074334 0.01025921 0.01203583
#2: 0.7660531 0.38785690 0.02915124
#3: 0.9806915 0.76869710 0.74974435
#4: 0.8514646 0.58068312 0.60675647
#5: 0.7901598 0.01171158 0.56948643
#6: 0.6283120 0.13738082 0.53516038
基准
在更大的数据集上
set.seed(24)
x1 <- as.data.frame(matrix(rnorm(5000*2000), ncol=5000))
set.seed(42)
colnames(x1) <- sample(paste0('prot', 1:100), 5000, replace=TRUE)
library(gtools)
nm2 <- mixedsort(unique(colnames(x1)))
dt2 <- as.data.table(matrix(NA, ncol= length(nm2),
nrow=nrow(x1), dimnames=list(NULL, nm2)))
setDT(x1)
system.time({
for(j in seq_along(dt1)){
set(dt2, i=NULL, j=j, value= do.call(pmax,x1[,colnames(x1) %chin%
nm2[j], with=FALSE]))
}
})
# user system elapsed
# 0.019 0.000 0.019
数据
x <- structure(list(cName = c("c1", "c2", "c3", "c4", "c5", "c6"),
prot1 = c(0.889618286, 0.766053072, 0.399227213, 0.089657475,
0.341599883, 0.627587607), prot1 = c(0.907433399, 0.061778787,
0.980691544, 0.353170832, 0.790159839, 0.363081942), prot1 =
c(0.085730039,
0.193634896, 0.30179994, 0.85146464, 0.653031942, 0.628312001
), prot2 = c(0.010259207, 0.387856898, 0.768697098, 0.580683125,
0.011711575, 0.137380824), prot3 = c(0.01203583, 0.029151237,
0.749744349, 0.606756472, 0.569486433, 0.535160381)),
.Names = c("cName",
"prot1", "prot1", "prot1", "prot2", "prot3"), class = "data.frame",
row.names = c(NA, -6L))
添加到 Akrun 的回答中:
第一个解决方案适用于小型数据集,但假设您的变量按 ascending/alphabetical 顺序排列。如果您的变量未排序,您可以使用以下内容(使用 Akrun 的 post 中的 x):
x1 <- data.frame(sapply(split(1:ncol(x), colnames(x)), function(i) do.call(pmax, x[i])))
到 2000 年,我有一个很大的 table 5000,其值如下。 我需要删除具有相同名称的列,同时保留列中每个位置的最大值(对于所有重复项)。
我卡住了..我有一个类似的代码,用于按行名删除重复项
x <- setDT(x)[, lapply(.SD, max), cName]
但我不知道如何使用相同的技巧,只能按列
prot1 prot1 prot1 prot2 prot3
0.889618286 0.907433399 0.085730039 0.010259207 0.01203583
0.766053072 0.061778787 0.193634896 0.387856898 0.029151237
0.399227213 0.980691544 0.30179994 0.768697098 0.749744349
0.089657475 0.353170832 0.85146464 0.580683125 0.606756472
0.341599883 0.790159839 0.653031942 0.011711575 0.569486433
0.627587607 0.363081942 0.628312001 0.137380824 0.535160381
所以清理后的版本是
prot1 prot2 prot3
0.907433399 0.010259207 0.01203583
0.766053072 0.387856898 0.029151237
0.980691544 0.768697098 0.749744349
0.85146464 0.580683125 0.606756472
0.790159839 0.011711575 0.569486433
0.628312001 0.137380824 0.535160381
在 base R
中,我们可以使用 'x' 的唯一列创建一个新数据集 ('x1')。按列名称拆分 'prot' 列的序列,使用该索引对 'x' 进行子集化,使用 pmax
获取每行的 max
值,并在列表中分配输出到 'x1'.
x1 <- x[unique(colnames(x))]
x1[-1] <- lapply(split(2:ncol(x), colnames(x)[-1]),
function(i) do.call(pmax, x[i]))
x1
# cName prot1 prot2 prot3
#1 c1 0.9074334 0.01025921 0.01203583
#2 c2 0.7660531 0.38785690 0.02915124
#3 c3 0.9806915 0.76869710 0.74974435
#4 c4 0.8514646 0.58068312 0.60675647
#5 c5 0.7901598 0.01171158 0.56948643
#6 c6 0.6283120 0.13738082 0.53516038
或者使用data.table
,我们可以得到向量中唯一列名的索引('nm1'),创建一个'data.table',列数等于'nm1' 和与原始数据集相同的行数 ('dt1')。将 data.frame
转换为 data.table
(setDT
)。使用 for
循环,我们可以 set
'dt1' 的每一列中的值作为 'x' 中每个唯一列名称的行的最大值(do.call(pmax,
).
library(data.table)
nm1 <- unique(colnames(x)[-1])
dt1 <- as.data.table(matrix(NA, ncol=length(nm1), nrow=nrow(x),
dimnames=list(NULL, nm1)))
setDT(x)
for(j in seq_along(dt1)){
set(dt1, i=NULL, j=j, value= do.call(pmax,x[,colnames(x) %chin%
nm1[j], with=FALSE]))
}
dt1
# prot1 prot2 prot3
#1: 0.9074334 0.01025921 0.01203583
#2: 0.7660531 0.38785690 0.02915124
#3: 0.9806915 0.76869710 0.74974435
#4: 0.8514646 0.58068312 0.60675647
#5: 0.7901598 0.01171158 0.56948643
#6: 0.6283120 0.13738082 0.53516038
基准
在更大的数据集上
set.seed(24)
x1 <- as.data.frame(matrix(rnorm(5000*2000), ncol=5000))
set.seed(42)
colnames(x1) <- sample(paste0('prot', 1:100), 5000, replace=TRUE)
library(gtools)
nm2 <- mixedsort(unique(colnames(x1)))
dt2 <- as.data.table(matrix(NA, ncol= length(nm2),
nrow=nrow(x1), dimnames=list(NULL, nm2)))
setDT(x1)
system.time({
for(j in seq_along(dt1)){
set(dt2, i=NULL, j=j, value= do.call(pmax,x1[,colnames(x1) %chin%
nm2[j], with=FALSE]))
}
})
# user system elapsed
# 0.019 0.000 0.019
数据
x <- structure(list(cName = c("c1", "c2", "c3", "c4", "c5", "c6"),
prot1 = c(0.889618286, 0.766053072, 0.399227213, 0.089657475,
0.341599883, 0.627587607), prot1 = c(0.907433399, 0.061778787,
0.980691544, 0.353170832, 0.790159839, 0.363081942), prot1 =
c(0.085730039,
0.193634896, 0.30179994, 0.85146464, 0.653031942, 0.628312001
), prot2 = c(0.010259207, 0.387856898, 0.768697098, 0.580683125,
0.011711575, 0.137380824), prot3 = c(0.01203583, 0.029151237,
0.749744349, 0.606756472, 0.569486433, 0.535160381)),
.Names = c("cName",
"prot1", "prot1", "prot1", "prot2", "prot3"), class = "data.frame",
row.names = c(NA, -6L))
添加到 Akrun 的回答中: 第一个解决方案适用于小型数据集,但假设您的变量按 ascending/alphabetical 顺序排列。如果您的变量未排序,您可以使用以下内容(使用 Akrun 的 post 中的 x):
x1 <- data.frame(sapply(split(1:ncol(x), colnames(x)), function(i) do.call(pmax, x[i])))