我想调整val列,以便不会有任何负值。
调整规则是,
xdat <- data.frame(
hier = c(rep("A",5), rep("B",5) )
, val = c(4, 7, -3, 10, 5, 1, -7, -4, 5, 7)
)
hier | val | val_adjust
A | 4 | 4
A | 7 | 7
A | -3 | 3.5
A | 10 | 10
A | 5 | 5
B | 1 | 1
B | -7 | 0.5
B | -4 | 0.25
B | 5 | 5
B | 7 | 7
你可以使用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
在生成可重现的问题时找到答案
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))
生成
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