Здравствуйте, я хочу знать, какой идентификатор и в каком году в приведенной выше таблице относятся только к людям со всеми предметными столбцами. Результаты должны быть такими, как показано ниже:
Я попробовал что-то вроде приведенного ниже кода, но это не дало мне идеального ответа.
df %>%
mutate(across(ends_with("sub"), is.na)) %>%
pivot_longer(-ID, names_to = "sub") %>%
filter(value) %>%
group_by(ID) %>%
summarise(`Missing Variables` = toString(sub))
Кроме того, в качестве дополнительной информации я хотел бы знать, есть ли способ изменить только определенные столбцы, например, только по математике и компьютеру, и посмотреть, какой идентификатор и год имеют оба этих предмета NA?
Большое спасибо!





Инстинктивно я бы использовал rowSums() применительно к is.na() рассматриваемых столбцов.
sub_cols <- grep("sub$", names(dat), value = TRUE)
dat[
rowSums(is.na(dat[sub_cols])) == length(sub_cols),
c("ID", "Year")
]
# ID Year
# 5 5 2016
# 6 6 2015
dplyr подходНа самом деле мне довольно неудобно выполнять матричные операции с помощью dplyr, но я бы это сделал следующим образом:
library(dplyr)
dat %>%
filter(
rowSums(!is.na(select(., ends_with("sub")))) == 0
) %>%
select(ID, Year)
# ID Year
# 5 5 2016
# 6 6 2015
data.table подходДля полноты картины вот подход data.table. Вы можете использовать шаблоны ("sub$") для выбора столбцов, оканчивающихся на "sub", и вы можете использовать rowSums() с .SD, так что в целом я думаю, что это самый хороший подход:
library(data.table)
setDT(dat)
dat[
dat[, rowSums(!is.na(.SD)) == 0, .SDcols = patterns("sub$")],
.(ID, Year)
]
# ID Year
# <int> <int>
# 1: 5 2016
# 2: 6 2015
dat <- structure(list(ID = 1:6, Year = c(2010L, 2015L, 2012L, 2015L,
2016L, 2015L), Maths_sub = c(20L, 17L, NA, 14L, NA, NA), Eng_sub = c(15L,
20L, 17L, 13L, NA, NA), Chem_sub = c(12L, 14L, 12L, NA, NA, NA
), Comp_sub = c(NA, 16L, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, -6L))
@JilberUrbina, конечно, короче, но на мой вкус слишком много волшебных чисел.
Другой вариант — добавить filter строки, в которых все значения равны NA, для каждой группы следующим образом:
library(dplyr)
df %>%
group_by(Year) %>%
filter(if_all(Maths_sub:Comp_sub, ~is.na(.)))%>%
select(-c(Maths_sub:Comp_sub))
#> # A tibble: 2 × 2
#> # Groups: Year [2]
#> ID Year
#> <int> <int>
#> 1 5 2016
#> 2 6 2015
Created on 2024-05-08 with reprex v2.1.0
Еще один вариант с основанием R, похожий на ваш:
dat[rowSums(is.na(dat[,-c(1,2)]))==4, 1:2]