我有一个很长的数据集,其中包含许多学期的学生成绩和课程。每个学生都有很多NA和许多行。我希望每个学生都有一排长长的行来填写这些NA,但要保留相同的列名。
这里是一个示例:
library(tidyverse)
sample <- tibble(student = c("Corey", "Corey", "Sibley", "Sibley"),
fall_course_1 = c("Math", NA, "Science", NA),
fall_course_2 = c(NA, "English", NA, NA),
fall_grade_1 = c(90, NA, 98, NA),
fall_grade_2 = c(NA, 60, NA, NA))
这是我想要的样子:
library(tidyverse)
answer <- tibble(student = c("Corey", "Sibley"),
fall_course_1 = c("Math", "Science"),
fall_course_2 = c("English", NA),
fall_grade_1 = c(90, 98),
fall_grade_2 = c(60, NA))
[有些学期,有些学生上许多课,有些只是一堂。我已经尝试过使用Coalesce(),但无法弄清楚。任何帮助,将不胜感激!
您可以获得每个student
在每一列中的第一个非NA值。
library(dplyr)
sample %> group_by(student) %>% summarise_all(~na.omit(.)[1])
# A tibble: 2 x 5
# student fall_course_1 fall_course_2 fall_grade_1 fall_grade_2
# <chr> <chr> <chr> <dbl> <dbl>
#1 Corey Math English 90 60
#2 Sibley Science NA 98 NA
如果组中存在所有NA
值,则此方法返回NA
。
使用自定义的colaesce函数和dplyr:
coalesce_all_columns <- function(df) {
return(coalesce(!!! as.list(df)))
}
library(dplyr)
sample %>%
group_by(student) %>%
summarise_all(coalesce_all_columns)
# A tibble: 2 x 5
student fall_course_1 fall_course_2 fall_grade_1 fall_grade_2
<chr> <chr> <chr> <dbl> <dbl>
1 Corey Math English 90 60
2 Sibley Science NA 98 NA
这应该执行,将数据旋转较长的长度,删除na,然后将其旋转回到较宽的位置。
您需要暂时将数值转换为字符,以便它们可以与课程标签放在同一列中,然后type_convert()是重新放回它们的一种惰性方法。
library(dplyr)
library(tidyr)
library(readr)
reshaped <- sample %>%
mutate_if(is.numeric, as.character) %>%
pivot_longer(-student) %>%
drop_na() %>%
pivot_wider(student, names_from = name, values_from = value) %>%
type_convert()
您还可以如下使用data.table包:
library(data.table)
setDT(sample)[, lapply(.SD, na.omit), student]
sample
# 1: Corey Math English 90 60
# 2: Sibley Science <NA> 98 NA