2017-09-05 59 views
0

我有如下所示的用例。基本上我有一个三列数据框。我想分两列(c1,c2)和总结第三个c3。然后,我只想挑选顶部1 c1最多c3(在所有c2之间),即排序将是不必要的,因为我只对最大值感兴趣。如何获得每列有多列的顶层元素?

library(plyr) 

df <- data.frame(c1=c('a','a','a','b','b','c'),c2=c('x','y','y','x','y','x'),c3=c(1,2,3,4,5,6)) 
df 
    c1 c2 c3 
1 a x 1 
2 a y 2 
3 a y 3 
4 b x 4 
5 b y 5 
6 c x 6 

sel <- plyr::ddply(df, c('c1','c2'), plyr::summarize,c3=sum(c3)) 
sel[with(sel, order(c1,-c3)),] 
    c1 c2 c3 
2 a y 5 <<< this one highest c3 for (c1,c2) combination 
1 a x 1 
4 b y 5 <<< this one highest c3 for (c1,c2) combination 
3 b x 4 
5 c x 6 <<< this one highest c3 for (c1,c2) combination 

我可以在循环中做到这一点,但我想知道如何以矢量方式或使用高级功能。

+0

另一种选择由C1 + C2组总结C3之后,你只有每C1的第1个一行+ C2。 –

+0

事实上,你是对的。我编辑了这个问题。我对'c1'感兴趣,在'c2'上最大'c3' –

回答

4

这里有一个基础R方法:

df2 <- aggregate(c3~c1+c2, df, sum) 
subset(df2[order(-df2$c3),], !duplicated(c1)) 
# c1 c2 c3 
#3 c x 6 
#4 a y 5 
#5 b y 5 
+0

不错,我喜欢它,因为它很简单,只使用base ...但是,我担心'!duplicate'位,因为存在没有规范合同,它必须选择第一个找到的......这是一个实施选择,如果改变,那么解决方案会打破或? –

+0

@GiovanniAzua,不知道我理解你的问题。此方法通过减少c3-sum来排序,然后每c1选取第一行(=最大c3行)。如果你以后想做点什么,显然这种方法也必须改变 –

3

dplyr的另一个解决方案。

library(dplyr) 

df2 <- df %>% 
    group_by(c1, c2) %>% 
    summarise(c3 = sum(c3)) %>% 
    filter(c3 == max(c3)) 

df2 
# A tibble: 3 x 3 
# Groups: c1 [3] 
     c1  c2 c3 
    <fctr> <fctr> <dbl> 
1  a  y  5 
2  b  y  5 
3  c  x  6 
2

使用dplyr

df %>% 
    group_by(c1, c2) %>% 
    summarise(c3 = sum(c3)) %>% 
    top_n(1, c3) 

或最后一行可以slice(which.max(c3)),这将保证一行。

3

这里是data.table

library(data.table) 
setDT(df)[, .(c3 = sum(c3)) , .(c1, c2)][, .SD[which.max(c3)], .(c1)] 
# c1 c2 c3 
#1: a y 5 
#2: b y 5 
#3: c x 6