【问题标题】:Calculate difference between values in consecutive rows by group按组计算连续行中的值之间的差异
【发布时间】:2023-03-19 09:51:01
【问题描述】:

这是我的df(data.frame):

group value
1     10
1     20
1     25
2     5
2     10
2     15 

我需要按组计算连续行中的值之间的差异。

所以,我需要一个这样的结果。

group value diff
1     10    NA # because there is a no previous value
1     20    10 # value[2] - value[1]
1     25    5  # value[3] value[2]
2     5     NA # because group is changed
2     10    5  # value[5] - value[4]
2     15    5  # value[6] - value[5]

虽然,我可以使用ddply 处理这个问题,但它需要太多时间。这是因为我的df 中有很多组。 (我的df 中有超过 1,000,000 个群组)

有没有其他有效的方法来处理这个问题?

【问题讨论】:

    标签: r


    【解决方案1】:

    使用shift 函数,包data.table 可以相当快地做到这一点。

    require(data.table)
    df <- data.table(group = rep(c(1, 2), each = 3), value = c(10,20,25,5,10,15))
    #setDT(df) #if df is already a data frame
    
    df[ , diff := value - shift(value), by = group]    
    #   group value diff
    #1:     1    10   NA
    #2:     1    20   10
    #3:     1    25    5
    #4:     2     5   NA
    #5:     2    10    5
    #6:     2    15    5
    setDF(df) #if you want to convert back to old data.frame syntax
    

    或者使用dplyr中的lag函数

    df %>%
        group_by(group) %>%
        mutate(Diff = value - lag(value))
    #   group value  Diff
    #   <int> <int> <int>
    # 1     1    10    NA
    # 2     1    20    10
    # 3     1    25     5
    # 4     2     5    NA
    # 5     2    10     5
    # 6     2    15     5
    

    对于data.table::shift 和dplyr::lag 之前的替代方案,请参阅编辑。

    【讨论】:

    • 您知道 ddply 解决方案吗?在我推断可能需要不同的功能之前,我已经为此工作了一段时间。 . .
    • 我认为它会类似于ddply(df, .(group), transform, diff=c(NA,diff(value)))
    • 如何修改它来计算百分比变化?
    • 您可以在此处应用任何功能。例如,如果这是我们的函数:perc_change &lt;- function(x, y) { return(x/y*100) },那么我们可以将其称为 df[ , perc_diff := perc_change(value, shift(value)), by = group]
    • 如何将 NA 替换为下一个值,以便第 1 行的 Diff 也像第 2 行一样为 10?
    【解决方案2】:

    您可以为此使用基本函数ave()

    df <- data.frame(group=rep(c(1,2),each=3),value=c(10,20,25,5,10,15))
    df$diff <- ave(df$value, factor(df$group), FUN=function(x) c(NA,diff(x)))
    

    返回

      group value diff
    1     1    10   NA
    2     1    20   10
    3     1    25    5
    4     2     5   NA
    5     2    10    5
    6     2    15    5
    

    【讨论】:

    • 相关问题:stackoverflow.com/questions/30378946/… 我发现这两个线程都有帮助。对于日期,您可以使用:df$diff &lt;- ave(as.numeric(df$Datevalue), factor(df$group), FUN=function(x) c(NA,diff(x))) 此外,如果您希望组中的最后一行具有 NA,则可以切换 NA 的位置。 df$diff &lt;- ave(as.numeric(df$Datevalue), factor(df$group), FUN=function(x) c(diff(x), NA))
    【解决方案3】:

    用 tapply 试试这个

    df$diff<-as.vector(unlist(tapply(df$value,df$group,FUN=function(x){ return (c(NA,diff(x)))})))
    

    【讨论】:

    • 这是我必须做的:df$diff &lt;- unlist(tapply(df$value,df$group, function(x) c(NA,diff(x))))
    猜你喜欢
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多