从两列中查找滚动最小和最大出现次数
Find rolling min and max occurrences from two columns
我想跟踪两列中的最小和最大出现次数。这应该从数据开始以滚动方式完成,因此我们可以跟踪每个日期总体 ID 出现的次数。同样,ID 出现在哪个列中也无关紧要。
结果应该如下。第 1 行,B 或 C 均未发生,因此 min_appearance 为 0 但 max_appearance 为 1,因为存在 A 和 D。第 5 行 A 和 D 在这一点上出现了 3 次,但 B 和 C 只有 2 次。我不关心哪个 ID 存在,但只关心最小值和最大值。而且真实数据更复杂,所以对不是静态的,但是A可以面对C等等。
# A tibble: 8 x 5
date id1 id2 min_appearances max_appearances
<date> <chr> <chr> <dbl> <dbl>
1 2020-01-01 A D 0 1
2 2020-01-02 B C 1 1
3 2020-01-03 C B 1 2
4 2020-01-04 D A 2 2
5 2020-01-05 A D 2 3
6 2020-01-06 B C 3 3
7 2020-01-07 C B 3 4
8 2020-01-08 D A 4 4
数据:
library(dplyr)
date <- seq(as.Date("2020/1/1"), by = "day", length.out = 8)
id1 <- rep(c("A", "B", "C", "D"), 2)
id2 <- rep(c("D", "C", "B", "A"), 2)
dt <- tibble(date = date,
id1 = id1,
id2 = id2)
这是一种使用 tidyverse
中的函数来实现的方法。首先,pivot_longer 处理数据更容易。然后计算每个唯一值 ids
的累积值计数。计算“计数”列中每一行的最小值和最大值。最后,取每对的最后一个最小值和最大值,然后转向宽。
library(tidyverse)
dt %>%
pivot_longer(cols = -date, values_to = "id") %>%
mutate(map_dfc(unique(id), ~ tibble("count_{.x}" := cumsum(id == .x)))) %>%
mutate(min_appearances = do.call(pmin, select(., starts_with("count"))),
max_appearances = do.call(pmax, select(., starts_with("count")))) %>%
group_by(date) %>%
mutate(across(min_appearances:max_appearances, last),
n = row_number()) %>%
pivot_wider(c(date, min_appearances, max_appearances), names_from = n, values_from = id, names_prefix = "id") %>%
relocate(order(colnames(.)))
date id1 id2 max_appearances min_appearances
<date> <chr> <chr> <int> <int>
1 2020-01-01 A D 1 0
2 2020-01-02 B C 1 1
3 2020-01-03 C B 2 1
4 2020-01-04 D A 2 2
5 2020-01-05 A D 3 2
6 2020-01-06 B C 3 3
7 2020-01-07 C B 4 3
8 2020-01-08 D A 4 4
我想跟踪两列中的最小和最大出现次数。这应该从数据开始以滚动方式完成,因此我们可以跟踪每个日期总体 ID 出现的次数。同样,ID 出现在哪个列中也无关紧要。
结果应该如下。第 1 行,B 或 C 均未发生,因此 min_appearance 为 0 但 max_appearance 为 1,因为存在 A 和 D。第 5 行 A 和 D 在这一点上出现了 3 次,但 B 和 C 只有 2 次。我不关心哪个 ID 存在,但只关心最小值和最大值。而且真实数据更复杂,所以对不是静态的,但是A可以面对C等等。
# A tibble: 8 x 5
date id1 id2 min_appearances max_appearances
<date> <chr> <chr> <dbl> <dbl>
1 2020-01-01 A D 0 1
2 2020-01-02 B C 1 1
3 2020-01-03 C B 1 2
4 2020-01-04 D A 2 2
5 2020-01-05 A D 2 3
6 2020-01-06 B C 3 3
7 2020-01-07 C B 3 4
8 2020-01-08 D A 4 4
数据:
library(dplyr)
date <- seq(as.Date("2020/1/1"), by = "day", length.out = 8)
id1 <- rep(c("A", "B", "C", "D"), 2)
id2 <- rep(c("D", "C", "B", "A"), 2)
dt <- tibble(date = date,
id1 = id1,
id2 = id2)
这是一种使用 tidyverse
中的函数来实现的方法。首先,pivot_longer 处理数据更容易。然后计算每个唯一值 ids
的累积值计数。计算“计数”列中每一行的最小值和最大值。最后,取每对的最后一个最小值和最大值,然后转向宽。
library(tidyverse)
dt %>%
pivot_longer(cols = -date, values_to = "id") %>%
mutate(map_dfc(unique(id), ~ tibble("count_{.x}" := cumsum(id == .x)))) %>%
mutate(min_appearances = do.call(pmin, select(., starts_with("count"))),
max_appearances = do.call(pmax, select(., starts_with("count")))) %>%
group_by(date) %>%
mutate(across(min_appearances:max_appearances, last),
n = row_number()) %>%
pivot_wider(c(date, min_appearances, max_appearances), names_from = n, values_from = id, names_prefix = "id") %>%
relocate(order(colnames(.)))
date id1 id2 max_appearances min_appearances
<date> <chr> <chr> <int> <int>
1 2020-01-01 A D 1 0
2 2020-01-02 B C 1 1
3 2020-01-03 C B 2 1
4 2020-01-04 D A 2 2
5 2020-01-05 A D 3 2
6 2020-01-06 B C 3 3
7 2020-01-07 C B 4 3
8 2020-01-08 D A 4 4