R按标识符合并列
R coalesce down columns by identifer
我有一个很长的数据集,其中包含跨多个学期的学生成绩和课程。每个学生都有很多 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(),但我想不通。如有任何帮助,我们将不胜感激!
使用自定义 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
您可以获得每个 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
个值,则此方法 returns 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
我有一个很长的数据集,其中包含跨多个学期的学生成绩和课程。每个学生都有很多 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(),但我想不通。如有任何帮助,我们将不胜感激!
使用自定义 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
您可以获得每个 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
个值,则此方法 returns 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