#r #loops #bigdata #tibble
#r #циклы #bigdata #tibble
Вопрос:
Я хочу создать новый столбец, который состоит из последнего значения из предыдущего периода для того же идентификатора, помещенного в ту же строку, что и первое значение для следующего периода. Если предыдущего периода нет, следует применить NA.
Однако я не могу найти никаких функций ни в каких пакетах, чтобы решить эту проблему для меня, поэтому я ожидаю, что мне придется написать цикл?
Есть ли у кого-нибудь идеи, как решить это аккуратным способом (с циклом или без него), который можно применить к большому tibble ( 4 миллиона наблюдений)?
Мои данные упорядочены как следующий df, а цель — df1:
df <- tibble(
ID = rep(c(77,88,99),each=6),
PERIOD = rep(c(1,2,3,1,2,3,1,2,3),each=2),
DATE = seq(as.Date("2020-06-01"), as.Date("2020-06-18"), by= "days"),
RESULT = seq(from = 10, to = 44, by = 2)
)
df
# A tibble: 18 x 4
ID PERIOD DATE RESULT
<dbl> <dbl> <date> <dbl>
1 77 1 2020-06-01 10
2 77 1 2020-06-02 12
3 77 2 2020-06-03 14
4 77 2 2020-06-04 16
5 77 3 2020-06-05 18
6 77 3 2020-06-06 20
7 88 1 2020-06-07 22
8 88 1 2020-06-08 24
9 88 2 2020-06-09 26
10 88 2 2020-06-10 28
11 88 3 2020-06-11 30
12 88 3 2020-06-12 32
13 99 1 2020-06-13 34
14 99 1 2020-06-14 36
15 99 2 2020-06-15 38
16 99 2 2020-06-16 40
17 99 3 2020-06-17 42
18 99 3 2020-06-18 44
df1 <- tibble(
ID = rep(c(77,88,99),each=6),
PERIOD = rep(c(1,2,3,1,2,3,1,2,3),each=2),
DATE = seq(as.Date("2020-06-01"), as.Date("2020-06-18"), by= "days"),
RESULT = seq(from = 10, to = 44, by = 2),
RESULT_post = c("NA","NA",12,"NA",16,"NA","NA","NA",24,"NA",28,
"NA","NA", "NA",36, "NA",40, "NA" )
)
df1
# A tibble: 18 x 5
ID PERIOD DATE RESULT RESULT_pre
<dbl> <dbl> <date> <dbl> <chr>
1 77 1 2020-06-01 10 NA
2 77 1 2020-06-02 12 NA
3 77 2 2020-06-03 14 12
4 77 2 2020-06-04 16 NA
5 77 3 2020-06-05 18 16
6 77 3 2020-06-06 20 NA
7 88 1 2020-06-07 22 NA
8 88 1 2020-06-08 24 NA
9 88 2 2020-06-09 26 24
10 88 2 2020-06-10 28 NA
11 88 3 2020-06-11 30 28
12 88 3 2020-06-12 32 NA
13 99 1 2020-06-13 34 NA
14 99 1 2020-06-14 36 NA
15 99 2 2020-06-15 38 36
16 99 2 2020-06-16 40 NA
17 99 3 2020-06-17 42 40
18 99 3 2020-06-18 44 NA
Все входные данные приветствуются
Спасибо / Sophia
Ответ №1:
Вот способ с dplyr
:
library(dplyr)
df %>%
group_by(ID, PERIOD) %>%
summarise(RESULT_pre = last(RESULT)) %>%
mutate(RESULT_pre = lag(RESULT_pre)) %>%
left_join(df, by = c('ID', 'PERIOD')) %>%
group_by(ID, PERIOD) %>%
mutate(RESULT_pre = replace(RESULT_pre, -1, NA)) %>%
select(-RESULT_pre, RESULT_pre)
# ID PERIOD DATE RESULT RESULT_pre
# <dbl> <dbl> <date> <dbl> <dbl>
# 1 77 1 2020-06-01 10 NA
# 2 77 1 2020-06-02 12 NA
# 3 77 2 2020-06-03 14 12
# 4 77 2 2020-06-04 16 NA
# 5 77 3 2020-06-05 18 16
# 6 77 3 2020-06-06 20 NA
# 7 88 1 2020-06-07 22 NA
# 8 88 1 2020-06-08 24 NA
# 9 88 2 2020-06-09 26 24
#10 88 2 2020-06-10 28 NA
#11 88 3 2020-06-11 30 28
#12 88 3 2020-06-12 32 NA
#13 99 1 2020-06-13 34 NA
#14 99 1 2020-06-14 36 NA
#15 99 2 2020-06-15 38 36
#16 99 2 2020-06-16 40 NA
#17 99 3 2020-06-17 42 40
#18 99 3 2020-06-18 44 NA
Логика здесь заключается в том, чтобы суммировать last
RESULT
значение для каждого ID
и PERIOD
и использовать lag
для сдвига значения в каждом ID
. Мы объединяем этот результат с исходным набором данных и сохраняем только первое значение в каждой группе и заменяем все остальные значения на NA
.
Ответ №2:
Вы можете скопировать все сдвинутые значения и перезаписать те, которые не соответствуют NA
:
n <- nrow(df)
df$RESULT_pre <- c(NA, df$RESULT[-n])
df$RESULT_pre[c(FALSE, df$ID[-1] != df$ID[-n] |
df$PERIOD[-1] == df$PERIOD[-n])] <- NA
df
# ID PERIOD DATE RESULT RESULT_pre
#1 77 1 2020-06-01 10 NA
#2 77 1 2020-06-02 12 NA
#3 77 2 2020-06-03 14 12
#4 77 2 2020-06-04 16 NA
#5 77 3 2020-06-05 18 16
#6 77 3 2020-06-06 20 NA
#7 88 1 2020-06-07 22 NA
#8 88 1 2020-06-08 24 NA
#9 88 2 2020-06-09 26 24
#10 88 2 2020-06-10 28 NA
#11 88 3 2020-06-11 30 28
#12 88 3 2020-06-12 32 NA
#13 99 1 2020-06-13 34 NA
#14 99 1 2020-06-14 36 NA
#15 99 2 2020-06-15 38 36
#16 99 2 2020-06-16 40 NA
#17 99 3 2020-06-17 42 40
#18 99 3 2020-06-18 44 NA