R函数根据条件进行汇总(总和x [y> 0])

时间:2020-08-24 14:30:27

标签: r aggregate

我的问题如下。

说,对于数据集中的每个度量,我都有一个带有标识符“ A”的data.frame。另外,我有一个时间值(数字)和一个差异值(数字)。数据集看起来像这样:

df <- data.frame(Identifier = c("A","A","A","A","A","A","A","A"),
                 Time_between = c(15, 25, 5, 6, 17, 9, 28, 3),
                 Difference = c(3, 15, -8, 7, 16, 29, 2, 0))
#>   Identifier Time_between Difference
#> 1          A           15          3
#> 2          A           25         15
#> 3          A            5         -8
#> 4          A            6          7
#> 5          A           17         16
#> 6          A            9         29
#> 7          A           28          2
#> 8          A            3          0

我想实现的是Time_between的累积值,但仅使用与差> 0有关的值。因此,差的第三个值-8应该得出累积值中未使用的值“ 5”。

我尝试编写一个函数,其中:

sum_if<- function(h,i){
  sum(h[i>0])}      

但是综合使用此功能会给我多个错误消息:

trial<-aggregate(df$time_between, by=df["Identifier"],    
                    FUN=function(h,i) sum_if(df$time_between, df$diff))    
Error in sum(h[i > 0]) : invalid 'type' (character) of argument    

我的数据框非常大(> 100万个观测值x 25个变量),所以这是我使用的数据的简化版本。

另外,我想得到一个小于0的值,求和重新开始。


尝试了一些建议的答案后的其他信息。

我遇到了一些问题。使用plyr讨论第一个选项确实可以在我在本文中创建的数据集中使用,但是在将其应用到我现有的较大数据集中时会遇到问题。也许有些现实:

df <- data.frame(Identifier = c("A","A","B","C","C","C","D","E"),
             Time_between = c(NA, 25, NA, NA, 17, 9, NA, NA),
             Difference = c(NA, 15, NA, NA, 16, -239, NA, NA))    

NA适用于信息,因此不应忽略。例如: 如果标识符A具有一个NA和25(“间隔时间”),则表示第二个处方的时间为第一个之后的25天。举例来说,如果第一次是在时间点10进行规定,而第二次是在时间点25,则相差15。

我尝试使用以下方法做第一个选择:

 df_trial<- df_trial %>% group_by(Studienummer) %>% 
  mutate(condsumPlyr=cumsum(df_trial$time_between)*(df_trial$diff_A>0)) %>%
  ungroup()    

这导致错误: 错误:mutate()输入condsumPlyr出现问题。 x输入condsumPlyr无法回收为大小1。 i输入condsumPlyrcumsum(df_trial$time_between) * (df_trial$diff_A > 0)。 i输入condsumPlyr的大小必须为1,而不是10576。 i错误发生在第1组:标识符= 59。

我尝试的第二件事是使用:

df_trial[,(consumDT:= cumsum(time_between*(diff_A>0))), by=Identifier]    

不起作用的错误: 未使用的参数(by =标识符)

最后,使用以下代码:

df_trial$cumsumBR <- sapply(split(df_trial, df_trial$Studienummer), 
  function(df_trial)cumsum(df_trial$time_between * (df_trial$diff_A > 0)))

发生以下错误: $<-.data.frame*tmp*中的错误,cumsumBR,值= list(59 = NA_real_,: 替换项有3106行,数据项有10576

我不确定哪个选项能满足我的首选结果,但是它们似乎都不起作用。

旁注:在我给出的“简单”数据集上,确实获得了预期的结果。谢谢!

1 个答案:

答案 0 :(得分:1)

如果要保留结构,可以使用布尔值来模拟ifelse(比ifelse更快),并使用cumsum来获取累积和。使用dplyr,我们可以得到可读的表达式来执行计算。

library(dplyr)
library(tidyr)
df <- df %>% 
  group_by(Identifier) %>% 
  mutate(condsumdPlyr = cumsum(Time_between * (Difference > 0))) %>%
  ungroup()

data.tabledisk.frame中,我们将使用它们的标准符号

library(data.table)
setDT(df) #change df to data.table
df[, consumDT := cumsum(Time_between * ( Difference > 0 ) ), by = Identifier]
# Alternative: df[Difference > 0, consumDT := cumsum(Time_between), by = Identifier]
setDF(df) #Only to change it back to a data.frame

在基数R中,我们想使用aggregate,但是由于我们需要使用多列,因此使用splitsapply更为简单(类似于tapply如何用于数组)

df$consumBase <- sapply(split(df, df$Identifier), function(df)cumsum(df$Time_between * (df$Difference > 0)))

现在,如果您坚决使用aggregate,则生命将变得更加复杂,因为它打算用于单列聚合。我们可以使用subset参数来解决问题,但这会删除正确的索引,并且很难将结果与原始data.frame合并

condDf <- aggregate(Time_between ~ Identifier, data = df, FUN = cumsum, subset = df$Difference > 0)
condDf <- data.frame(Identifier = rep(condDf$Identifier, lengths(condDf$Time_between)), condsumAggregate = unlist(condDf$Time_between))

Ofc。如果我们length(unique(df$Identifier))为1,这将变得更加简单,因为我们不需要对数据进行分组。

免责声明:如果没有数据,我将无法正确测试其拼写错误