我有data frame
,(我只显示df
的尾部)此数据框名为conv2
8464 208394_x_at ESM1 -1.035878e-01
8468 200858_s_at SNORD55 -1.034971e-01
8469 200858_s_at SNORD38B -1.034971e-01
8467 200858_s_at RPS8 -1.034971e-01
8472 207381_at RPS8 -1.034510e-01
8477 211197_s_at ICOSLG -1.033752e-01
我想要的是,只要在第二列中重复了一个名称,例如RPS8
,就删除所有包含此名称的行,除了第三列的absoulte值最高的行。因此,在示例中,行8467
将被删除。
我这样做了
for (d in dup){
conv2 <- rbind(conv2, conv[which(conv$SYMBOL == d),][which.max(abs(conv[which(conv$SYMBOL == d),][,3])),])
}
有更好更快的方法吗?
答案 0 :(得分:4)
我们可以使用
library(dplyr)
conv2 %>%
group_by(col1, col2) %>%
slice(which.max(abs(col3)))
更快的选择是
conv2 %>%
group_by(col1, col2) %>%
arrange(desc(abs(col3))) %>%
slice(1)
或者我们可以使用data.table
library(data.table)
setDT(conv2)[order(-abs(col3)), .SD[1L], .(col1, col2)]
注意:应更改列名称(因为示例中未显示)
答案 1 :(得分:2)
以下是使用“split-apply-combine”方法的基础R解决方案。
# split data.frame by column 2
myList <- split(conv2, conv2$col2)
# loop through list of data.frames and rbind observations with maximum values
dfNew <- do.call(rbind, lapply(myList, function(i) i[which.max(abs(i$col3)),]))
答案 2 :(得分:0)
如果你想使用for循环执行相同的逻辑,你可以尝试这种方式,但是之前的OP已经显示了一种简单的方法,而不是使用for循环
df1 <- data.frame(col1 = NA, col2 = NA, col3 = NA)
for(i in unique(df$col2)){
x <- max(df$col3[df$col2==i])
df12 <- unique(df[df$col3==x & df$col2==i,])
df1 <- rbind(df1,print(df12))
df1 <- df1[!is.na(df1$col1),]
}
print(df1)
col1 col2 col3
2 208394_x_at ESM1 -1.035878
21 200858_s_at SNORD55 -1.034971
3 200858_s_at SNORD38B -1.034971
5 207381_at RPS8 -1.034510
6 211197_s_at ICOSLG -1.033752
df <- data.frame(col1 =c("208394_x_at","200858_s_at","200858_s_at","200858_s_at","207381_at","211197_s_at"),
col2 = c("ESM1","SNORD55","SNORD38B","RPS8","RPS8","ICOSLG"),
col3 = c(-1.035878,-1.034971,-1.034971,-1.034971,-1.034510,-1.033752),stringsAsFactors=F)