首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何基于具有名称类型的变量在R中进行筛选和计数

如何基于具有名称类型的变量在R中进行筛选和计数
EN

Stack Overflow用户
提问于 2021-07-01 13:47:10
回答 1查看 400关注 0票数 2

我在R中有如下教育数据:

代码语言:javascript
复制
df <- data.frame(
   "StudentID" = c(101, 102, 103, 104, 105, 106, 111, 112, 113, 114, 115, 116, 121, 122, 123, 124, 125, 126),
   "FedEthn" = c(1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3),
   "HIST.11.LEV" = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 5, 3, 3),
   "HIST.11.SCORE" = c(96, 95, 95, 97, 88, 99, 89, 96, 79, 83, 72, 95, 96, 93, 97, 98, 96, 87),
   "HIST.12.LEV" = c(2, 2, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 4, 3, 3, 3, 3, 3),
   "SCI.9.LEV" = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3),
   "SCI.9.SCORE" = c(91, 99, 82, 95, 65, 83, 96, 97, 99, 94, 95, 96, 89, 78, 96, 95, 97, 90),
   "SCI.10.LEV" = c(1, 2, 1, 2, 1, 1, 3, 3, 2, 2, 2, 3, 3, 3, 4, 3, 4, 3)
)

##    StudentID  FedEthn  HIST.11.LEV  HIST.11.SCORE  HIST.12.LEV  SCI.9.LEV  SCI.9.SCORE  SCI.10.LEV
## 1        101        1            1             96            2          1           91           1
## 2        102        1            1             95            2          1           99           2
## 3        103        2            1             95            1          1           82           1
## 4        104        2            1             97            2          1           95           2
## 5        105        3            1             88            1          1           65           1
## 6        106        3            1             99            1          1           83           1
## 7        111        1            2             89            2          2           96           3
## 8        112        1            2             96            3          2           97           3
## 9        113        2            2             79            2          2           99           2
## 10       114        2            2             83            2          2           94           2
## 11       115        3            2             72            2          2           95           2
## 12       116        3            2             95            2          2           96           3
## 13       121        1            3             96            4          3           89           3
## 14       122        1            3             93            3          3           78           3
## 15       123        2            3             97            3          3           96           4
## 16       124        2            3             98            3          3           95           3
## 17       125        3            3             96            3          3           97           4
## 18       126        3            3             87            3          3           90           3

在11年级的历史课程中,level代表了学生的学术水平。(5 =最高学历,1=最低学历。例如,5可能是AP或IB课程。HIST.11.SCORE表示学生在课程中的分数。

当学生在某门课程中获得95分或以上时,他们有资格在下一年提升到更高的学术水平(例如HIST.12.LEV =1+ HIST.11.LEV)。然而,只有一些符合条件的学生才会升迁,而老师必须同意这一点。我正在分析的是,符合条件的学生的升学率是否因据报的联邦种族不同而不同。

到目前为止,我是如何做到这一点的:

代码语言:javascript
复制
var.level <- 1
var.ethn <- 1

actual.move.ups <- 
  (df %>% filter(FedEthn==var.ethn,
                 HIST.11.LEV==var.level,
                 HIST.11.SCORE>94,
                 HIST.12.LEV==var.level+1) %>% 
     count) +
  (df %>% filter(FedEthn==var.ethn,
                 SCI.9.LEV==var.level,
                 SCI.9.SCORE>94,
                 SCI.10.LEV==var.level+1) %>% 
     count)

eligible.move.ups <- 
  (df %>% filter(FedEthn==var.ethn,
                 HIST.11.LEV==var.level,
                 HIST.11.SCORE>94) %>% 
     count) +
  (df %>% filter(FedEthn==var.ethn,
                 SCI.9.LEV==var.level,
                 SCI.9.SCORE>94) %>% 
     count)

这是可行的,我可以从1:5迭代var.level,从1:7迭代var.ethnicity,并将结果存储在数据框架中。但是在我的实际数据中,这种方法需要对df %>%过滤器(.) %>%计数进行15次迭代(我会将它们全部加起来)。原因是,在我的实际数据中,有15个机会跨越5个科目(HIST、SCI、数学、ENG、WL)和4个年级(9、10、11、12年级)。

我的问题是,是否有一种更紧凑的方法来过滤和计数COURSE.GRADE.LEV==i、COURSE.GRADE+1.LEV==i+1和COURSE.GRADE.SCORE>94的所有实例,而无需键入/硬编码每个课程名称(HIST、SCI、数学、ENG、WL)和每个年级(9、10、11、12)。那么,在数据帧中存储结果的最佳方法是什么?

对于上面的示例数据,这是理想的输出。不过,数据框架不需要有这种精确的结构。

代码语言:javascript
复制
##    FedEthn  L1.Actual  L1.Eligible  L2.Actual  L2.Eligible  L3.Actual  L3.Eligible
## 1        1          3            3          3            3          1            1
## 2        2          2            3          0            1          1            3
## 3        3          0            1          1            3          1            2

*注意:我读过this helpful answer,但是对于我的变量名,级别(9、10、11、12)没有一致的字符串位置(例如,SCI.9与HIST.11)。另外,在某些情况下,我需要多次计算单个行,因为单个学生可以在多个班级中向上移动。也许解决办法是在执行计数之前,将数据从宽到长进行整形?

EN

回答 1

Stack Overflow用户

发布于 2021-07-01 18:22:00

使用@akrun的this great answer,我想出了一个解决方案。不过,我想我还是把事情弄得太复杂了,我希望能接受别人更简洁的回答。

代码语言:javascript
复制
course.names <- c("HIST.","SCI.")
grade.levels <- 9:11

tally.actual <- function(var.ethn, var.level){
  total.tally.actual <- NULL
  for(i in course.names){
    course.tally.actual <- NULL
    for(j in grade.levels){
      new.tally.actual <- df %>% filter(
        FedEthn == var.ethn,
        !!(rlang::sym(paste0(i,j,".LEV"))) == var.level,
        !!(rlang::sym(paste0(i,(j+1),".LEV"))) == (var.level+1),
        !!(rlang::sym(paste0(i,j,".SCORE"))) > 94
      ) %>% count
      course.tally.actual <- c(new.tally.actual, course.tally.actual)
    }
    total.tally.actual <- c(total.tally.actual, course.tally.actual)
  }
  return(sum(unlist(total.tally.actual)))
}

tally.eligible <- function(var.ethn, var.level){
  total.tally.eligible <- NULL
  for(i in course.names){
    course.tally.eligible <- NULL
    for(j in grade.levels){
      new.tally.eligible <- df %>% filter(
        FedEthn == var.ethn,
        !!(rlang::sym(paste0(i,j,".LEV"))) == var.level,
        !!(rlang::sym(paste0(i,j,".SCORE"))) > 94
      ) %>% count
      course.tally.eligible <- c(new.tally.eligible, course.tally.eligible)
    }
    total.tally.eligible <- c(total.tally.eligible, course.tally.eligible)
  }
  return(sum(unlist(total.tally.eligible)))
}

results <- data.frame("FedEthn" = 1:3, 
                      "L1.Actual" = NA, "L1.Eligible" = NA, 
                      "L2.Actual" = NA, "L2.Eligible" = NA, 
                      "L3.Actual" = NA, "L3.Eligible" = NA)

for(var.ethn in 1:3){
  for(var.level in 1:3){
    results[var.ethn,(var.level*2)] <- tally.actual(var.ethn,var.level)
    results[var.ethn,(var.level*2+1)] <- tally.eligible(var.ethn,var.level)
  }
}

这种方法可以工作,但是它需要df包含每一个组合--当然(SCI,数学,HIST,ENG,WL)和年份(9,10,11,12)。有关我是如何添加到原始df的,请参见下面的内容。包括所有可能的组合对于我的实际数据来说都不是问题,但我希望有一种解决方案,不需要添加一堆填充NA的列:

代码语言:javascript
复制
df$HIST.9.LEV = NA
df$HIST.9.SCORE = NA
df$HIST.10.LEV = NA
df$HIST.10.SCORE = NA
df$HIST.12.SCORE = NA
df$SCI.10.SCORE = NA
df$SCI.11.LEV = NA
df$SCI.11.SCORE = NA
df$SCI.12.LEV = NA
df$SCI.12.SCORE = NA
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68211397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档