【问题标题】:cumsum with reset at flagged column in r?在r中的标记列重置的cumsum?
【发布时间】:2019-02-25 02:06:42
【问题描述】:

这是我第一次提出问题,请多多包涵。

我的数据集(df)是这样的:

animal   azimuth   south   distance
 pb1      187.561   1       1.992 
 pb1      147.219   1       8.567
 pb1      71.032    0       5.754
 pb1      119.502   1       10.451
 pb2      101.702   1       9.227
 pb2      85.715    0       8.821

我想创建一个额外的列 (df$cumdist) 来增加累积距离,但在每个单独的动物内并且仅当 df$south==1 时。我希望用df$south==0 重置累积和。

这就是我想要的结果(手动完成):

animal   azimuth   south   distance  cumdist
 pb1      187.561   1       1.992     1.992
 pb1      147.219   1       8.567     10.559 
 pb1      71.032    0       5.754     0 
 pb1      119.502   1       10.451    10.451
 pb2      101.702   1       9.227     9.227 
 pb2      85.715    0       8.821     0

这是我尝试实现 cumsum 的代码:

swim.az$cumdist <- cumsum(ifelse(swim.az$south==1, swim.az$distance, 0))

虽然在df$south==0 时成功停止添加,但不会重置。此外,我知道我需要将其嵌入到 for 循环中,以按动物进行子集。

非常感谢!

【问题讨论】:

    标签: r for-loop if-statement cumsum


    【解决方案1】:

    我们将 'south' 与 'distance' ('cumdist') 相乘以将 'south' 中的 0 对应的 'distance' 中的值更改为 0,按 'animal' 分组,并通过获取累积值创建的组逻辑向量的总和(south == 0),得到'cumdist'的cumsumungroup并删除不需要的列(grp

    library(dplyr)
    dfN %>% 
      mutate(cumdist = south * distance) %>%
      group_by(animal, grp = cumsum(south == 0)) %>%
      mutate(cumdist = cumsum(cumdist)) %>%
      ungroup %>%
      select(-grp)
    # A tibble: 6 x 5
    #  animal azimuth south distance cumdist
    #  <chr>    <dbl> <int>    <dbl>   <dbl>
    #1 pb1      188.      1     1.99    1.99
    #2 pb1      147.      1     8.57   10.6 
    #3 pb1       71.0     0     5.75    0   
    #4 pb1      120.      1    10.5    10.5 
    #5 pb2      102.      1     9.23    9.23
    #6 pb2       85.7     0     8.82    0   
    

    base R 的类似方法

    with(dfN, ave(distance * south, animal, cumsum(!south), FUN = cumsum))
    #[1]  1.992 10.559  0.000 10.451  9.227  0.000
    

    数据

    dfN <- structure(list(animal = c("pb1", "pb1", "pb1", "pb1", "pb2", 
    "pb2"), azimuth = c(187.561, 147.219, 71.032, 119.502, 101.702, 
    85.715), south = c(1L, 1L, 0L, 1L, 1L, 0L), distance = c(1.992, 
    8.567, 5.754, 10.451, 9.227, 8.821)), class = "data.frame", 
    row.names = c(NA, -6L))
    

    【讨论】:

    • 非常好!还有一个问题:我们怎样才能得到所有十进制数字的结果? (就像 Ryan 的回答中的结果)
    • @GeorgeDontas 这只是tibble 的打印方法。您可以使用%&gt;% as.data.frame 包装输出以查看值。实际上,价值就在那里
    • 我相信他们是。我的观点是,我发现这种行为非常具有误导性,我想知道是否有一些选择可以改变它。
    • 如果您想更永久地更改它,您可以随时覆盖小标题的打印方法,即print.tbl_df &lt;- print.data.frame
    【解决方案2】:
    library(data.table)
    setDT(df)
    
    df[, cumdist := south*cumsum(distance), .(animal, rleid(south))]
    
    #    animal azimuth south distance cumdist
    # 1:    pb1 187.561     1    1.992   1.992
    # 2:    pb1 147.219     1    8.567  10.559
    # 3:    pb1  71.032     0    5.754   0.000
    # 4:    pb1 119.502     1   10.451  10.451
    # 5:    pb2 101.702     1    9.227   9.227
    # 6:    pb2  85.715     0    8.821   0.000
    

    【讨论】:

    • 我用rleid()太少了..很有用!
    • 哇!谢谢你这么快的回复!它奏效了,而且比我预期的要简单得多!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多