#r #dplyr #subset
#r #дплыр #подмножество #dplyr
Вопрос:
Итак, у меня есть набор данных следующего вида:
ID Var1 Var2
1 2 0
1 8 0
1 12 0
1 11 1
1 10 1
2 5 0
2 8 0
2 7 0
2 6 1
2 5 1
Я хотел бы подмножить фрейм данных и создать новый фрейм данных, содержащий только строки после того, как Var1 впервые достиг своего группового максимума (включая строку, в которой это происходит), вплоть до строки, в которой Var2 впервые становится 1 (также включая эту строку). Итак, то, что я хотел бы иметь, должно выглядеть примерно так:
ID Var1 Var2
1 12 0
1 11 1
2 8 0
2 7 0
2 6 1
Исходный набор данных содержит несколько NAS, и функция должна просто игнорировать их. Также, если Var2 никогда не достигает «1» для группы, следует просто добавить все строки в новый фрейм данных (конечно, только те, которые после того, как Var1 достигнет своего группового максимума).
Однако я не могу обернуть свою руку вокруг программирования. Кто-нибудь знает помощь?
Ответ №1:
dplyr
Решение на cumsum
основе filter
будет делать то, что требует вопрос.
library(dplyr)
df1 %>%
group_by(ID) %>%
filter(cumsum(Var1 == max(Var1)) == 1, cumsum(Var2) <= 1)
## A tibble: 5 x 3
## Groups: ID [2]
# ID Var1 Var2
# <int> <int> <int>
#1 1 12 0
#2 1 11 1
#3 2 8 0
#4 2 7 0
#5 2 6 1
Редактировать
Вот решение, которое пытается ответить на комментарий OP и редактировать вопрос.
df1 %>%
group_by(ID) %>%
mutate_at(vars(starts_with('Var')), ~replace_na(., 0L)) %>%
filter(cumsum(Var1 == max(Var1)) == 1, cumsum(Var2) <= 1)
Данные
df1 <- read.table(text = "
ID Var1 Var2
1 2 0
1 8 0
1 12 0
1 11 1
1 10 1
2 5 0
2 8 0
2 7 0
2 6 1
2 5 1
", header = TRUE)
Комментарии:
1. большое спасибо за ваш ответ. Однако это не работает на 100% правильно для фактического набора данных. Для большинства групп остается только одна строка, чего не может быть. Как решение справляется с NAs и если в Var2 нет «1»? Я просто отредактировал вопрос, чтобы сделать это более понятным
2. @philipp.kn_98 Посмотрите, отвечает ли решение в редактировании на вопрос.
Ответ №2:
Использование data.table
с .I
library(data.table)
setDT(df1)[df1[, .I[cumsum(Var1 == max(Var1)) amp; cumsum(Var2) <= 1], by="ID"]$V1]
# ID Var1 Var2
#1: 1 12 0
#2: 1 11 1
#3: 2 8 0
#4: 2 7 0
#5: 2 6 1
данные
df1 <- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L),
Var1 = c(2L, 8L, 12L, 11L, 10L, 5L, 8L, 7L, 6L, 5L), Var2 = c(0L,
0L, 0L, 1L, 1L, 0L, 0L, 0L, 1L, 1L)), class = "data.frame",
row.names = c(NA,
-10L))
Ответ №3:
Вот data.table
перевод рабочего решения Руи Баррадаса:
library(data.table)
dat <- fread(text = "
ID Var1 Var2
1 2 0
1 8 0
1 12 0
1 11 1
1 10 1
2 5 0
2 8 0
2 7 0
2 6 1
2 5 1
", header = TRUE)
dat[, .SD[cumsum(Var1 == max(Var1)) amp; cumsum(Var2) <= 1], by="ID"]