如何解决r 中的惩罚累积和
我需要计算一个受罚的累积总和。
个人“A”、“B”和“C”应该每隔一年接受一次测试。每次他们接受测试,他们都会累积 1 分。但是,当他们错过考试时,他们的累积分数会被扣除 1 分。
data.frame(year = rep(1990:1995,3),person.id = c(rep("A",6),rep("B",rep("C",6)),needs.testing = rep(c("Yes","No"),9),test.compliance = c(c(1,1,0),c(1,0)),penalized.compliance.cum.sum = c(c(1,2,3,1),-1,-1)))
...给出以下内容:
year person.id needs.testing test.compliance penalized.compliance.cum.sum
1 1990 A Yes 1 1
2 1991 A No 0 1
3 1992 A Yes 1 2
4 1993 A No 0 2
5 1994 A Yes 1 3
6 1995 A No 0 3
7 1990 B Yes 1 1
8 1991 B No 0 1
9 1992 B Yes 1 2
10 1993 B No 0 2
11 1994 B Yes 0 1
12 1995 B No 0 1
13 1990 C Yes 1 1
14 1991 C No 0 1
15 1992 C Yes 0 0
16 1993 C No 0 0
17 1994 C Yes 0 -1
18 1995 C No 0 -1
很明显,“A”完全符合要求。 “B”有点符合(1994年他应该接受测试,但他错过了测试,因此他的累计金额从2减为1)。最后,“C”只符合了一次(1990 年,每次她需要接受测试,她都错过了测试)。
我需要一些代码来获取“penalized.compliance.cum.sum”变量。
请注意:
- 每隔一年进行一次测试。
- “penalized.compliance.cum.sum”变量不断增加之前的分数。
- 但只有当个人错过测试年度的测试(在“needs.testing”变量中表示)时才会开始扣除。
- 例如,个人“C”在 1990 年符合要求。在 1991 年她不需要接受测试,因此她的分数保持为 1。然后,她错过了 1992 年的测试,并且从她的累积分数中减去了 1 ,在 1992 年得了 0 分。然后她一直错过考试,在研究结束时得了 -1。
- 此外,我需要分配不同的惩罚(即不同的数字)。在此示例中,它只是 1。但是,我需要能够使用其他数字(例如 0.5、0.1 等)进行惩罚。
谢谢!
解决方法
基础 R
do.call(rbind,by(dat,dat$person.id,function(z) transform(z,res = cumsum(ifelse(needs.testing == "Yes",1-2*(test.compliance < 1),0)))
))
# year person.id needs.testing test.compliance penalized.compliance.cum.sum res
# A.1 1990 A Yes 1 1 1
# A.2 1991 A No 0 1 1
# A.3 1992 A Yes 1 2 2
# A.4 1993 A No 0 2 2
# A.5 1994 A Yes 1 3 3
# A.6 1995 A No 0 3 3
# B.7 1990 B Yes 1 1 1
# B.8 1991 B No 0 1 1
# B.9 1992 B Yes 1 2 2
# B.10 1993 B No 0 2 2
# B.11 1994 B Yes 0 1 1
# B.12 1995 B No 0 1 1
# C.13 1990 C Yes 1 1 1
# C.14 1991 C No 0 1 1
# C.15 1992 C Yes 0 0 0
# C.16 1993 C No 0 0 0
# C.17 1994 C Yes 0 -1 -1
# C.18 1995 C No 0 -1 -1
by
通过 INDICES
(此处为 dat$person.id
)分割一个帧,其中函数 z
是该组的数据。这使我们可以对数据进行操作,而不必担心人物在向量中发生变化。
by
返回一个 list
,将列表组合成一个框架的规范 base-R 方式是 rbind(a,b)
当只有两个框架时,或者 do.call(rbind,list(...))
在列表中超过两帧。
1-2*(.)
只是基于 test.compliance
在 +1 和 -1 之间徘徊的技巧。
这具有潜在改变行顺序的副作用。例如,如果先按 year
然后按 person.id
排序,那么 by
-group 计算仍然很好,但输出将按 person.id
(和由组内的 year
排序)。次要,但如果你需要秩序,请注意它。
dplyr
library(dplyr)
dat %>%
group_by(person.id) %>%
mutate(res = cumsum(if_else(needs.testing == "Yes",0))) %>%
ungroup()
数据表
library(data.table)
datDT <- as.data.table(dat)
datDT[,res := cumsum(fifelse(needs.testing == "Yes",0)),by = .(person.id)]
,
这可能对你有用吗?
df <- data.frame(year = rep(1990:1995,3),person.id = c(rep("A",6),rep("B",rep("C",6)),needs.testing = rep(c("Yes","No"),9),test.compliance = c(c(1,1,0),c(1,penalized.compliance.cum.sum = c(c(1,2,3,1),-1,-1)))
library("dplyr")
penalty <- -1
df %>%
group_by(person.id) %>%
mutate(cumsum = cumsum(ifelse(needs.testing == "Yes" & test.compliance == 0,penalty,test.compliance)))
## A tibble: 18 x 6
## Groups: person.id [3]
# year person.id needs.testing test.compliance penalized.compliance.cum.sum cumsum
# <int> <chr> <chr> <dbl> <dbl> <dbl>
# 1 1990 A Yes 1 1 1
# 2 1991 A No 0 1 1
# 3 1992 A Yes 1 2 2
# 4 1993 A No 0 2 2
# 5 1994 A Yes 1 3 3
# 6 1995 A No 0 3 3
# 7 1990 B Yes 1 1 1
# 8 1991 B No 0 1 1
# 9 1992 B Yes 1 2 2
#10 1993 B No 0 2 2
#11 1994 B Yes 0 1 1
#12 1995 B No 0 1 1
#13 1990 C Yes 1 1 1
#14 1991 C No 0 1 1
#15 1992 C Yes 0 0 0
#16 1993 C No 0 0 0
#17 1994 C Yes 0 -1 -1
#18 1995 C No 0 -1 -1
然后您可以轻松地将 penalty
变量调整为您想要的任何惩罚。
使用 case_when
library(dplyr)
df1 %>%
group_by(person.id) %>%
mutate(res = cumsum(case_when(needs.testing == "Yes" ~ 1- 2 *(test.compliance < 1),TRUE ~ 0)))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。