一种选项是使用 rowwise
- 按行分组,使用 na.last
为 TRUE 进行 sort
,将排序后的输出保留在 list
中,对其进行 unnest
操作以展开为多列,并选择仅具有至少一个非-NA元素的列进行 select
library(dplyr)
library(tidyr)
library(stringr)
df1 %>%
rowwise %>%
transmute(ID, date = list(sort(c_across(starts_with('pick')),
na.last = TRUE))) %>%
ungroup %>%
unnest_wider(date) %>%
rename_with(~ str_c('date', seq_along(.)), -ID) %>%
select(where(~ any(!is.na(.))))
-输出
# A tibble: 4 × 3
ID date1 date2
<int> <chr> <chr>
1 1 21/11/29 21/11/30
2 2 21/11/28 21/11/29
3 3 21/11/28 21/11/30
4 4 21/11/29 21/11/30
或者使用将数据转换为“长”格式,删除值后再将其转换为“宽”格式。
library(stringr)
df1 %>%
pivot_longer(cols = -ID, values_drop_na = TRUE) %>%
group_by(ID) %>%
mutate(name = str_c('date', row_number())) %>%
ungroup %>%
pivot_wider(names_from = name, values_from = value)
-输出
# A tibble: 4 × 3
ID date1 date2
<int> <chr> <chr>
1 1 21/11/29 21/11/30
2 2 21/11/28 21/11/29
3 3 21/11/28 21/11/30
4 4 21/11/29 21/11/30
数据
df1 <- structure(list(ID = 1:4, pick1 = c(NA, "21/11/28", "21/11/28",
NA), pick2 = c("21/11/29", "21/11/29", NA, "21/11/29"), pick3 = c("21/11/30",
NA, "21/11/30", "21/11/30")), class = "data.frame",
row.names = c(NA,
-4L))
dplyr
并执行my_data %>% mutate(date1 = coalesce(pick2, pick1), date2 = coalesce(pick3, pick2)) %>% select(!starts_with("pick"))
。 - Greg