2016-08-01 61 views
2

我有一个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删除所有包含此名称的行,除了第三列中具有最高绝对值的行。因此在示例行8467将被删除。

我已经做了这样

for (d in dup){ 

    conv2 <- rbind(conv2, conv[which(conv$SYMBOL == d),][which.max(abs(conv[which(conv$SYMBOL == d),][,3])),]) 

} 

是否有这样做的更好,更快的方式?

回答

2

这是一个使用“拆分应用组合”方法的基础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)),])) 
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)] 

注:列名应改为(因为它不是s在这个例子中是如何)

0

如果你想用for循环做同样的逻辑,你可以尝试这种方式,但以往的OP表现出一种简单的方法,而不是使用循环

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)