如何按学期整理学生入学数据?

时间:2019-03-27 19:52:02

标签: r dplyr data-analysis

我有一个数据集,该数据集当前按学期列出学生信息(即201610、201620、201630、201640、201710等),后缀为10 =秋季,20 =冬季,30 =春季和40 =夏季。并非所有学生都必须列出所有术语。

我想做的是确定一个学生入学的第一学期,大概是秋季,即T1,随后的学期是T2,T3等。由于某些学生可能会参加冬季暑假,所以我会希望将其标识为T1_Winter,T2_Summer等。

我已经能够隔离出学生所注册的各个术语,并且能够将第一个,中间和最后一个术语标识为1、2、3等。但是,我无法管理围绕如何识别秋季和春季分别是1、2、3、4以及冬季和夏季以及1.5、2.5、3.5、4.5等的中间术语。

# Create the sample dataset
data <- data.frame(
  ID = c(1, 1, 1, 2, 2, 2, 2),
  RegTerm = c(201810, 201820, 201830, 201910, 201930, 201940, 202010))
)

# Isolate student IDs and terms
stdTerm <- subset(data, select = c("ID","RegTerm"))

# Sort according to ID and RegTerm
stdTerm <- stdTerm[
  with(stdTerm, order(ID, RegTerm)),
  ]

# Remove duplicate combinations of ID and term
y <- stdTerm[!duplicated(stdTerm[c(1,2)]),]

# Create an index to identify the term number
# for which a student enrolled
library(dplyr)
z <- y %>% 
  arrange(ID, RegTerm) %>% 
  group_by(ID) %>% 
  mutate(StdTermIndex = seq(n()))

现在,它会将学生的所有术语的进度标识为1、2、3等,但不能将冬季和夏季作为中间术语。也就是说,如果某个学生在秋季和冬季入学,则冬季将显示为2,而春季将显示为3。

在提供的示例数据中,我希望学生ID 1将201810反映为1,201820反映为1.5,将201830反映为2,依此类推。我可以参考的任何建议或以前的代码来包裹我的代码。中间学期?

2 个答案:

答案 0 :(得分:0)

我认为,执行此操作的一种好方法是将RegTerm列分为yearsuffix,然后在拆分值后应用一些条件公式。

下面的代码可以做到这一点,我们只需要将其应用于整个列并进行一些重新调整即可。

paste(strsplit(as.character(201810), "")[[1]][1:4], collapse = ""))
# "2018"
paste(strsplit(as.character(201810), "")[[1]][5:6], collapse = ""))
# "10"

因此,要在数据框上使用lapply之类的内容,然后取消列出结果并添加新列。之后,您可以将值更改为数字,然后在mutate函数中使用一些条件语句来设置中间值等。

z$year <- unlist(lapply(z$RegTerm, function(x) paste(strsplit(as.character(x), "")[[1]][1:4], collapse = "")))
z$suf <- unlist(lapply(z$RegTerm, function(x) paste(strsplit(as.character(x), "")[[1]][5:6], collapse = "")))

看起来有点难看,但是它所做的就是将RegTerm分开,然后分别选择year和suf的前4个或后2个字符,然后折叠(使用collapse = ""中的paste)他们成一个字符串。我们将lapply整列,然后将其取消列出以创建矢量。

我建议您理解此答案中的前两行代码,然后将其变得显而易见。

答案 1 :(得分:0)

因此,为了在您的示例中做到这一点,我创建了一个句柄变量,该变量告诉我RegTerm是偶数还是奇数。

原因很简单,奇数RegTerm表示它是一个常规术语,而偶数则是冬季或夏季术语。

library(dplyr)
data <- data.frame(
  ID = c(1, 1, 1, 2, 2, 2, 2),
  RegTerm = c(201810, 201820, 201830, 201910, 201930, 201940, 202010)
  )

dat <- data %>%
  mutate(term = str_extract(RegTerm, '(?<=\\d{4})\\d{1}(?=0)'),
         term = as.numeric(term) %% 2) %>%
  group_by(ID) %>%
  mutate(numTerm = cumsum(term),
         numTerm = ifelse(term == 0, numTerm + 0.5, numTerm))

第一个变异提取RegTerm列中的第5个数字并将其除以2。如果等于1,则表示它是一个常规术语,否则将是夏季或冬季。

接下来,我将求和该变量的总和,这将为您提供学生所在的RegTerm所在的位置。然后,我将每term == 0加到numTerm 0.5中,以说明冬季和夏季的条件。

# A tibble: 7 x 4
# Groups:   ID [2]
     ID RegTerm  term numTerm
  <dbl>   <dbl> <dbl>   <dbl>
1     1  201810     1     1  
2     1  201820     0     1.5
3     1  201830     1     2  
4     2  201910     1     1  
5     2  201930     1     2  
6     2  201940     0     2.5
7     2  202010     1     3  

这样,如果有一个学生从冬季学期开始,numTerm将被分配一个0.5的值,只有当他达到常规学期{{1}时才具有numTerm = 1 }