我在R中有以下数据框。它代表了一个简化的蛋白质结构,以便于解释。
Uniprots Chain resSeq Serial
P68871 D 23 3446
P68871 D 24 3453
P68871 D 25 3457
P68871 D 26 3461
P68871 D 27 3470
P69011 A 38 3561
P69011 A 39 3568
P69011 A 40 3577
P69011 A 41 3588
P69011 A 42 3599
P69011 A 43 3610
P69011 A 44 3619
P69011 A 45 3625
P69011 A 46 3636
P0116 B 2 4239
P0116 B 4 4242
P0116 B 5 4268
P0116 B 6 4279
P0116 B 7 4285
P0116 B 8 4299
P0116 B 9 5015
P0116 C 15 5055
P0116 C 30 5199
P0116 C 42 5239
我想要的是把它折叠起来,看起来像这样:
Uniprot Chain resSeq_start resSeq_end Serial_start Serial_end
P68871 D 23 27 3446 3470
P69011 A 38 46 3561 3636
P0116 B 2 9 4239 5015
P0116 C 15 42 5055 5239
基本上,我希望在前1,2和3列上向下折叠。然后我可以使用第4列作为检查它是否有效。我以为我可以用聚合来做到这一点,但这似乎不起作用。我肯定可以通过一些凌乱的for循环来做到这一点(继续附加到一个向量直到一个新的uniprot /链)但这很难看。
有一点需要注意的是,Uniprot / Chain组合并不总是唯一的。具体来说,uniprot可以有多个链(如我的例子)。
感谢您的帮助!
答案 0 :(得分:4)
当然还有dplyr
require(dplyr)
dat %>% group_by(Uniprots, Chain) %>%
summarize(resSeq_start = min(resSeq),
resSeq_end = max(resSeq),
Serial_start = min(Serial),
Serial_end = max(Serial))
答案 1 :(得分:3)
我推荐data.table。
这是一个简单的实现:
Step1:将data.frame转换为data.table:
library(data.table)
setDT(dt)
第2步:创建新列:
dt[, `:=`(resSeq_start = min(resSeq),
resSeq_end = max(resSeq),
Serial_start = min(Serial),
Serial_end = max(Serial)),
by = list(Uniprots, Chain)]
第3步:删除旧列:
res <- dt[, c("Serial", "resSeq") := NULL]
步骤4:仅保留唯一列:
unique(res, by=c("Uniprots", "Chain"))
# Uniprots Chain resSeq_start resSeq_end Serial_start Serial_end
# 1: P68871 D 23 27 3446 3470
# 2: P69011 A 38 46 3561 3636
# 3: P0116 B 2 9 4239 5015
# 4: P0116 C 15 42 5055 5239
我已经说明了使用data.table
引用添加/删除列的两种方法。一个使用c("col", "col2") := list(val1, val2)
,另一个使用`:=`(col1 = val1,col2 = val2)。
希望这会有所帮助。您应该阅读有关data.table的更多信息。
答案 2 :(得分:3)
aggregate
:@ user20650提供的基本解决方案(我更喜欢)(do.call
很重要,因为聚合将返回数据框,但带有矩阵元素)
do.call(data.frame, aggregate(cbind(resSeq, Serial) ~ Uniprots + Chain,
data = dat, function(x) c(start = min(x), end = max(x))))
# Uniprots Chain resSeq.start resSeq.end Serial.start Serial.end
# 1 P69011 A 38 46 3561 3636
# 2 P0116 B 2 9 4239 5015
# 3 P0116 C 15 42 5055 5239
# 4 P68871 D 23 27 3446 3470
plyr
dat <- psych::read.clipboard()
library(plyr)
ddply(dat, .(Uniprots, Chain), summarise,
resSeq_start = min(resSeq),
resSeq_end = max(resSeq),
Serial_start = Serial[which.min(resSeq)],
Serial_end = Serial[which.max(resSeq)])
# Uniprots Chain resSeq_start resSeq_end Serial_start Serial_end
# 1 P0116 B 2 9 4239 5015
# 2 P0116 C 15 42 5055 5239
# 3 P68871 D 23 27 3446 3470
# 4 P69011 A 38 46 3561 3636
(可能不需要.min / max)