将某些值的行与聚合相结合,然后将聚合子集返回到数据框

时间:2016-02-19 19:20:17

标签: r

新手再次来到这里,决心提出比我上次更好的可重复性问题。我的数据框:

> str(Denton)
'data.frame':   1666 obs. of  8 variables:
$ MIL.ID     : Factor w/ 18840 levels "","0000151472",..: 7393 3955 3955 3955 3871 3871 8627 8627 1609 11652 ...
$ Center     : int  8130 8130 8130 8130 8130 8130 8130 8130 8130 8130 ...
$ Gift.Date  : Factor w/ 339 levels "","01/01/2015",..: 3 6 6 6 7 7 7 7 8 8 ...
$ Gift.Amount: num  25 50 50 50 25 25 50 50 2500 20 ...
$ Solic.     : Factor w/ 31 levels "","aa","ac","an",..: 24 20 20 20 20 20 20 20 11 11 ...
$ Tender     : Factor w/ 10 levels "","c","ca","cc",..: 3 3 3 3 3 3 3 3 3 3 ...
$ Account    : Factor w/ 16 levels "","29101-0000",..: 2 2 2 2 2 2 2 2 2 2 ...
$ Restriction: Factor w/ 258 levels "","AAU","ACA",..: 1 43 43 43 43 43 43 43 43 43 ...

> head(Denton)
MIL.ID     Center   Gift.Date         Gift.Amount Solic. Tender    Account Restriction
0000741377   8130 01/02/2015           25          ps     ca       29101-0000            
0000551071   8130 01/05/2015           50          mem    ca       29101-0000 BWC
0000551071   8130 01/05/2015           50          mem    ca       29101-0000 BWC
0000551071   8130 01/05/2015           50          mem    ca       29101-0000 BWC
0000544358   8130 01/06/2015           25          mem    ca       29101-0000 BWC
0000544358   8130 01/06/2015           25          mem    ca       29101-0000 BWC

我的最终目标只是返回此数据框的摘要数据,但有一点需要注意:有一种投标类型“pd”,即工资扣除,每年发生26次。每项工资扣除在技术上都是一份礼品的一部分,即不是26件礼品,而是一份。我试图做的是结合与pd和MIL.ID(捐赠者ID)相关联的礼物金额,因此每个人的多个工资扣除被合并为一个礼物。这部分并不太难,我在其他一些关于堆栈溢出的例子中找到了一些帮助:

> df <- aggregate(Gift.Amount~MIL.ID,subset(Denton,Tender=="pd"),sum)
> head(df)
   MIL.ID     Gift.Amount
1 0000308080         324
2 0000308492          24
3 0000756682           4
4 0000757228          24
5 0000776957         850
6 0000777108         213

此数据框包含与工资扣减相关的MIL.ID,并将每个MIL.ID下的pd条目相加。现在,我的微弱大脑就会陷入困境。回想一下,我想简单地

summary(Denton)
一旦我在招标中将pd与他们相关的MIL.ID相加,就抓住手段和中位数。有问题的是,工资扣减的汇总数据现在仅作为独立的数据框架存在。我不知何故需要:

1)删除Tender下的旧pd行, 2)结合Denton和DF数据帧 3)总结数据

这是我在基地R中能够找到的:

>Denton[Denton$Tender!=pd,]

现在那些正在招标的原始pd已经消失了。但是,我不能把丹顿和df重新组合在一起,如:

>str(df)
data.frame':    77 obs. of  2 variables:
$ MIL.ID     : Factor w/ 18840 levels "","0000151472",..: 1613 1617 7967 7991 8627 8637 8797 8899 9807 11371 ...
$ Gift.Amount: num  324 24 4 24 850 213 360 4 11 24 ...

两个数据框都是矩形的,长度不同,所以R不能在没有踢出的情况下工作

Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 502, 77. 

基地R有没有办法解决这个问题,还是我需要下载重塑包并学习如何融化?我是否甚至需要通过使用聚合函数来使事情复杂化?

编辑评论:

Denton的当前头衔():

 > head(Denton)
MIL.ID     Center   Gift.Date         Gift.Amount Solic. Tender    Account Restriction
0000741377   8130 01/02/2015           25          ps     ca       29101-0000            
0000551071   8130 01/05/2015           50          mem    pd       29101-0000 BWC
0000551071   8130 01/05/2015           50          mem    pd       29101-0000 BWC
0000551071   8130 01/05/2015           50          mem    pd       29101-0000 BWC
0000544358   8130 01/06/2015           25          mem    pd       29101-0000 BWC
0000544358   8130 01/06/2015           25          mem    pd       29101-0000 BWC

一旦我想要完成的事情完成,所需的输出:

> head(Denton)
MIL.ID     Center   Gift.Date         Gift.Amount Solic. Tender    Account Restriction
0000741377   8130 01/02/2015           25          ps     ca       29101-0000            
0000551071   8130 01/05/2015          150          mem    pd       29101-0000 BWC
0000544358   8130 01/06/2015           50          mem    pd       29101-0000 BWC
0000556000   8130 01/05/2015           50          mem    ca       29101-0000 BWC
0000556005   8130 01/05/2015           50          mem    ca       29101-0000 BWC
0000556100   8130 01/05/2015           50          mem    ca       29101-0000 BWC

然后我会

>summary(Denton)

为了获得我的资金和中位数,现在已经为每个MIL.ID合并了招标中的pd。

Dplyr函数如何:

> Denton %>%
     group_by(MIL.ID) %>% #sorts by MIL.ID
     select(MIL.ID, Gift.Amount, Tender) %>% #selects these three for agg
     filter(sum(Tender) <= pd) %>% #I think this should sum where tender= pd?
     distinct #get distinct rows? 

1 个答案:

答案 0 :(得分:1)

以下是使用dplyr package的解决方案。它不是基础R,但是极大地简化了事情,因此非常值得添加到 R 工具中。 (抱歉,无法帮助自己...)

library(dplyr)
Denton <- data.frame("MIL.ID" = c(1,2,2,3,3,4),
                    "Tender" = c("ca", "pd", "pd", "pd", "pd", "ab"),
                    "Gift.Amount" = c(1,2,3,4,5,6),
                    "Solic" = c("ps", "mem", "mem", "mem", "mem", "ps")
                    )

这给出了

  MIL.ID Tender Gift.Amount Solic
1      1     ca           1    ps
2      2     pd           2   mem
3      2     pd           3   mem
4      3     pd           4   mem
5      3     pd           5   mem
6      4     ab           6    ps

现在,使用dplyr的功能来做你想做的事:

Denton %>% group_by(MIL.ID) %>%  # This groups by MIL.ID    
        mutate( Gift.Amount = sum(Gift.Amount)) %>%   # This gets the sum of each Gift.Amount
        distinct # This gets the distinct rows

输出:

Source: local data frame [4 x 4]
Groups: MIL.ID [4]

  MIL.ID Tender Gift.Amount  Solic
   (dbl) (fctr)       (dbl) (fctr)
1      1     ca           1     ps
2      2     pd           5    mem
3      3     pd           9    mem
4      4     ab           6     ps

备注

这假设对于给定的MIL.ID,除了Gift.Amount之外,所有pd行都是相似的,这看起来就像上面的例子一样。 (如果不是,那么请使用什么逻辑来更新您的问题,以确定要保留哪一行,并且我将更新我的答案以使用该逻辑。)

我还将sum放在所有Tenders上,而不仅仅是pd投标,因为一个项目的总和只是该项目的价值而且这样做意味着我不需要分开然后绑定两个不同的dfs。

修改

另一个选择是您可以将Denton df分成两个:

df_notpd <- Denton %>% filter(Tender != "pd");
df_pd <- Denton %>% filter(Tender == "pd");


# Now do the necessary logic on *only* the pd portion.
df_pd <- df_pd group_by(MIL.ID) %>%  # This groups by MIL.ID    
        mutate( Gift.Amount = sum(Gift.Amount)) %>%   # This gets the sum of each Gift.Amount
        distinct # This gets the distinct rows

# Then rbind back with df_notpd
df <- rbind(df_notpd, df_pd)