【发布时间】:2019-04-30 03:06:19
【问题描述】:
我有一个数据,我想从中获取以下信息。示例基于ID == 1。
- 每个 ID 的第一个日期及其对应的结果(对于
ID == 1其DATE == 1/3/2018)。如果有层级,则取最后一行 (RESULT == 110)。 - 每个 ID 的第二个日期及其对应的结果(对于
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)
采取的步骤:
- 将问题一分为二,一是按日期排序,二是按结果排序。
- 第一部分使用
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)
【问题讨论】: