微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

r 中的惩罚累积和

如何解决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”变量。

请注意

  1. 每隔一年进行一次测试。
  2. “penalized.compliance.cum.sum”变量不断增加之前的分数。
  3. 但只有当个人错过测试年度的测试(在“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 举报,一经查实,本站将立刻删除。