У меня есть данные, где я хотел бы получить следующую информацию.Пример основан на ID == 1
.
- Первая дата каждого идентификатора и соответствующий ему результат (для
ID == 1
его DATE == 1/3/2018
).Если есть уровни, возьмите последнюю строку (RESULT == 110
). - Вторая дата каждого идентификатора и соответствующий ему результат (для
ID == 1
его DATE == 2/3/2018
).Если есть уровни, возьмите последнюю строку (RESULT == 117
). - Самый низкий результат и соответствующую ему дату.Если наименьшее значение имеет 2 даты, выведите первую дату.Второй датой будет дата второго наименьшего результата.
- Второй наименьший результат и соответствующая ему дата.Если самое низкое значение отличается от самого низкого результата.
Данные:
df <- read.table(text = "
ID DATE RESULT
1 1/3/2018 110
1 1/3/2018 120
1 2/3/2018 115
1 2/3/2018 117
1 3/3/2018 100
1 4/3/2018 100
2 1/11/2018 110
2 1/11/2018 120
2 1/11/2018 108
2 2/11/2018 115
2 3/11/2018 80
2 4/11/2018 70", header = TRUE, stringsAsFactors = FALSE)
Желаемый результат:
df_out <- read.table(text = "
ID FIRST_DATE FIRST_RESULT SECOND_DATE SECOND_RESULT LOWEST_DATE LOWEST_RESULT SECOND_LOWEST_DATE SECOND_LOWEST_RESULT
1 2018-03-01 120 2018-03-02 117 2018-03-03 100 2018-03-04 100
2 2018-11-01 108 2018-11-02 115 2018-11-04 70 2018-11-03 80", header = TRUE, stringsAsFactors = FALSE)
Выполненные шаги:
- Разделите задачу на 2, одну, которая включает ранжирование по дате, а другую, включающую ранжирование по результату.
- Использование
dplyr::dense_rank
для первой части и dplyr::row_number
для второй части. - Возьмите
dplyr::full_join
, чтобы получить окончательный кадр данных.
Мой код работает отлично, но я чувствую, что онслишком долгоПоэтому я хотел бы спросить, может ли кто-нибудь написать это более кратко.
library(dplyr)
library(tidyr)
# First Portion
df_DATE <- df %>%
group_by(ID) %>%
mutate(DATE = dmy(DATE),
RANK_DATE = dense_rank(DATE)) %>%
group_by(ID, RANK_DATE) %>%
filter(RANK_DATE %in% 1:2,
row_number() == n()) %>%
ungroup() %>%
mutate(DATE = as.character(DATE)) %>%
gather(VARIABLE, VALUE, -c(ID, RANK_DATE)) %>%
unite(VARIABLE, VARIABLE, RANK_DATE) %>%
spread(VARIABLE, VALUE) %>%
select(ID,
FIRST_DATE = DATE_1, FIRST_RESULT = RESULT_1,
SECOND_DATE = DATE_2, SECOND_RESULT = RESULT_2)
# Second Portion
df_RESULT <- df %>%
group_by(ID) %>%
mutate(DATE = dmy(DATE),
RANK_RESULT = row_number(RESULT)) %>%
filter(RANK_RESULT %in% 1:2) %>%
mutate(DATE = as.character(DATE)) %>%
gather(VARIABLE, VALUE, -c(ID, RANK_RESULT)) %>%
unite(VARIABLE, VARIABLE, RANK_RESULT) %>%
spread(VARIABLE, VALUE) %>%
select(ID,
LOWEST_DATE = DATE_1, LOWEST_VALUE = RESULT_1,
SECOND_LOWEST_DATE = DATE_2, SECOND_LOWEST_VALUE = RESULT_2)
# Combine the 2 portions
df_out <- full_join(df_DATE, df_RESULT)