将负值替换为上一行/ 2

时间:2018-03-05 23:32:08

标签: r dplyr

我想调整val列,以便不会有任何负值。

Ajusting规则是,

  • 将负值替换为前一行的一半
  • 为每个hier(group_by(hier))
  • 执行此操作
  • 如果连续多个负值,则将之前的调整值除以2

    xdat %>% 
      rowid_to_column("rowid") %>% 
      group_by(hier) %>% 
      mutate(rowid = rank(rowid)) %>% 
      mutate(val_adj1 = lag(val)) %>% 
      mutate(val_adj1 = case_when(val < 0~val_adj1/2, TRUE~val)) %>% 
      mutate(val_adj2 = lag(val_adj1)) %>% 
      mutate(val_adj2 = case_when(val_adj1 < 0~val_adj2/2, TRUE~val_adj1))  
    

2 个答案:

答案 0 :(得分:2)

您可以使用accumulate

中的purrr
library(tidyverse)
 xdat%>%group_by(hier)%>%mutate(adj_val=accumulate(val,~ifelse(.y<0,.x/2,.y)))
# A tibble: 10 x 3
# Groups:   hier [2]
     hier   val adj_val
   <fctr> <dbl>   <dbl>
 1      A     4    4.00
 2      A     7    7.00
 3      A    -3    3.50
 4      A    10   10.00
 5      A     5    5.00
 6      B     1    1.00
 7      B    -7    0.50
 8      B    -4    0.25
 9      B     5    5.00
10      B     7    7.00

在基地R你可以做类似的事情:

transform(xdat,y=unlist(tapply(val,hier,FUN=Reduce,f=function(x,y)ifelse(y<0,x/2,y),accumulate=T)))
   hier val     y
A1    A   4  4.00
A2    A   7  7.00
A3    A  -3  3.50
A4    A  10 10.00
A5    A   5  5.00
B1    B   1  1.00
B2    B  -7  0.50
B3    B  -4  0.25
B4    B   5  5.00
B5    B   7  7.00

答案 1 :(得分:0)

在生成可重复的问题时找到答案

   rowid   hier   val val_adj1 val_adj2
   <dbl> <fctr> <dbl>    <dbl>    <dbl>
 1     1      A     4      4.0     4.00
 2     2      A     7      7.0     7.00
 3     3      A    -3      3.5     3.50
 4     4      A    10     10.0    10.00
 5     5      A     5      5.0     5.00
 6     1      B     1      1.0     1.00
 7     2      B    -7      0.5     0.50
 8     3      B    -4     -3.5     0.25
 9     4      B     5      5.0     5.00
10     5      B     7      7.0     7.00

产生

{{1}}