#r #dplyr
Вопрос:
У меня есть большой набор данных (500 000 строк) с идентификатором и днями недели (1-7), и я хочу удалить все строки после окончательного вхождения числа 7 дня недели для всех идентификаторов.
Вот упрощенный пример.
Набор данных:
df <- structure(list(A = structure(c(1L, 1L, 1L, 1L,1L,1L,1L,1L,1L,1L,1L,1L,1L, 2L, 2L, 2L, 2L, 2L,2L,2L,2L,2L, 3L, 3L, 3L,3L,3L,3L),
.Label = c("a", "b", "c"), class = "factor"),
B = c(1L, 7L, 1L, 1L, 2L, 7L, 1L, 2L, 3L, 1L, 2L, 7L,1L, 7L, 1L, 1L, 2L, 7L, 1L, 2L, 3L, 1L, 2L, 7L,1L, 1L, 2L, 7L)),
.Names = c("ID","Weekday"),
class = "data.frame",
row.names = c(NA, -28L))
Этот код отлично работает с этим упрощенным набором данных:
df.out<-df %>%
group_by(ID)%>%
dplyr::slice(1:max(which(Weekday == "7")))
Но когда я пробую это на своем большом наборе данных, я получаю следующую ошибку:
Error in 1:max(which(weekday == "7")) : result would be too long a vector
In addition: Warning message:
In max(which(weekday == "7")) :
no non-missing arguments to max; returning -Inf
Я пробовал использовать день недели как числовой, множитель и целое число, но безуспешно.
Похоже, я не могу воспроизвести эту ошибку в упрощенном наборе данных, подходящем для этой платформы, поэтому я не уверен, как ее продемонстрировать дальше, но буду признателен за любую помощь в том, как обойти эту ошибку!
Я использовал аналогичный код для большого набора данных, чтобы удалить все строки до первого появления без каких-либо проблем. Например.
df.out<-df %>%
group_by(ID)%>%
dplyr::slice(which.max(weekday == "1") : n())
Комментарии:
1. Попробуйте этот пример, проблема
which
в том, что у него нет совпадения:max(which(mtcars$cyl == 11))
Ответ №1:
Ошибка может быть воспроизведена, если у вас есть ID
ошибка, в которой нет 7.
library(dplyr)
df <- rbind(df, data.frame(ID = 'd', Weekday = 1))
df %>%
group_by(ID)%>%
slice(1:max(which(Weekday == "7")))
Ошибка в 1:макс(который(День недели == «7»)) : результат будет слишком длинным вектором
Решением было бы проверить, есть ли у вас хотя бы одно вхождение из 7.
df %>%
group_by(ID)%>%
slice(if(any(Weekday == 7)) 1:max(which(Weekday == 7)) else 0) %>%
ungroup
# ID Weekday
# <fct> <dbl>
# 1 a 1
# 2 a 7
# 3 a 1
# 4 a 1
# 5 a 2
# 6 a 7
# 7 a 1
# 8 a 2
# 9 a 3
#10 a 1
# … with 13 more rows
Комментарии:
1. В
slice
случае, если вы вернете 0, он не выберет ни одной строки. (Смmtcars %>% slice(0)
.). Так что это отбросит теID
, в которых нет 7.2. Извините, я не хотел удалять свой комментарий. Но спасибо, в этом есть смысл. Если бы я хотел, чтобы он нашел последнее вхождение 6, если нет 7, сработало бы это? df %>% group_by(ИДЕНТИФИКАТОР)%>>% срез(если(любой(Будний день == 7 )) 1:макс(какой(Будний день == 7)) еще если(любой(Будний день == 6 )) 1:макс(какой(Будний день == 6)))%>>>% разгруппировать
3. Да, и за этим следует,
else 0
если 6 нет.4. Отлично. Огромное спасибо!
Ответ №2:
Мы также можем сделать
library(dplyr)
df %>%
group_by(ID)%>%
slice(seq_len(max(c(0, which(Weekday == 7)[-1])))) %>%
ungroup
-выход
# A tibble: 23 x 2
ID Weekday
<fct> <dbl>
1 a 1
2 a 7
3 a 1
4 a 1
5 a 2
6 a 7
7 a 1
8 a 2
9 a 3
10 a 1
# … with 13 more rows
данные
df <- structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L,
3L, 3L, 3L, 3L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"),
Weekday = c(1, 7, 1, 1, 2, 7, 1, 2, 3, 1, 2, 7, 1, 7, 1,
1, 2, 7, 1, 2, 3, 1, 2, 7, 1, 1, 2, 7, 1)), row.names = c(NA,
-29L), class = "data.frame")
Ответ №3:
Вы также можете использовать следующее решение:
library(dplyr)
df %>%
group_by(ID) %>%
filter(between(row_number(), 1, which(Weekday == 7)[sum(Weekday == 7)]))
# A tibble: 23 x 2
# Groups: ID [3]
ID Weekday
<fct> <int>
1 a 1
2 a 7
3 a 1
4 a 1
5 a 2
6 a 7
7 a 1
8 a 2
9 a 3
10 a 1
# ... with 13 more rows