我试图计算有多少学生在他们的科目中得到了1、2、3、4和5,我希望为每门科目和可能的分数(math_1、science_2等)设置一列。
我最初写了一个for循环,但是我的实际数据集有太多的case,我需要使用map。我可以让它工作,但是它产生了许多NA,并且每列只有一个块有实际数据。我很好奇地想知道:
1.为什么map_df()会这样做?如何避免?或者
1.我怎样才能把这个数据集中起来,使第一个数据集中的原始行(18行)中只有一行有这个信息?换句话说,我将上下连接列,这样所有的NA都被填充了(除非真的有缺失数据)。
这是我的密码
library(tidyverse)
#Set up - generate sample dataset and get all combinations of grades and subjects
student_grades <- tibble(student_id = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5),
subject = c(rep(c("english", "biology", "math", "history"), 4), NA, "biology"),
grade = as.character(c(1, 2, 3, 4, 5, 4, 3, 2, 2, 4, 1, 1, 1, 1, 2, 3, 3, 4)))
all_subject_combos <- c("english", "history", "math", "biology")
all_grades <- c("1", "2", "3",
"4", "5")
subjects_and_letter_grades <- expand.grid(all_subject_combos, all_grades)
all_combos <- subjects_and_letter_grades %>%
unite("names", c(Var1, Var2)) %>%
mutate(names = str_replace_all(names, "\\|", "_")) %>%
pull(names)
# iterate over each combination using map_df()
student_map <- map_df(all_combos,
~student_grades %>%
mutate("{.x}" := paste(i)) %>%
group_by(student_id) %>%
mutate("{.x}" := sum(case_when(str_detect(.x, subject) &
str_detect(.x, grade) ~ 1,
TRUE ~ 0), na.rm = T)))
EDIT声明一下,我几乎相同的for循环并没有填充很多缺失的值,我认为这一定与构建数据集的方式有关,但我不知道如何覆盖map_df在幕后所做的事情。
student_map <- student_grades
for(i in all_combos) {
student_map <- student_map %>%
mutate("{i}" := paste(i)) %>%
group_by(student_id) %>%
mutate("{i}" := sum(case_when(str_detect(i, subject) &
str_detect(i, grade) ~ 1,
TRUE ~ 0), na.rm = T))
}
2条答案
按热度按时间332nm8kg1#
在
map
中没有i
,因为循环的默认lambda值是.x
。此外,最好使用transmute
而不是mutate
,因为我们只需要返回在每次迭代中添加的列,然后在最后绑定原始数据tf7tbtn22#
虽然我不明白map_df()为什么会以这种不受欢迎的方式执行,但我确实找到了一个解决方案,这主要是受answer to this post的启发。
基本上,这段代码删除了所有的NA,并且只在只有缺失值的情况下保留缺失值,因为我的数据集中的那些列永远不会有缺失值,所以这个解决方案在我的情况下是有效的。