R:每组外观重启计数器
R: Restart counter per group appearance
我读了很多书,测试了很多书,但都没有成功。
我希望为每个组创建一个计数器,但是这个 coutner 会在每次出现一个组时重新启动(即使它 "reappears")。
示例:
我需要一个 seq_along 每个 TYPE_OF_PROMOTION
重新启动每个组外观。
结果应该像 counter
由于促销 B 在第 18 周重新出现但是是新出现 - 重新启动计数器。
如果该解决方案也适用于 NA - 好的,我只是做了一个快速演示。
Week TYPE_OF_PROMOTION counter
11 11 <NA> NA
12 12 B 1
13 13 B 2
14 14 B 3
15 15 <NA> NA
16 16 <NA> NA
17 17 <NA> NA
18 18 B 1
19 19 B 2
20 20 <NA> NA
这里有一个 data.table
的选项。将 'data.frame' 转换为 'data.table' (setDT(df1)
),按 'TYPE_OF_PROMOTION' 的 运行-length-id 分组,创建行序列 (seq_len(.N)
) 乘以在 'TYPE_OF_PROMOTION' 中具有 NA
的值以创建 'counter' 列
library(data.table)
setDT(df1)[, counter2 := seq_len(.N) * NA^is.na(TYPE_OF_PROMOTION),
by = rleid(TYPE_OF_PROMOTION)]
df1
# Week TYPE_OF_PROMOTION counter counter2
# 1: 11 <NA> NA NA
# 2: 12 B 1 1
# 3: 13 B 2 2
# 4: 14 B 3 3
# 5: 15 <NA> NA NA
# 6: 16 <NA> NA NA
# 7: 17 <NA> NA NA
# 8: 18 B 1 1
# 9: 19 B 2 2
#10: 20 <NA> NA NA
或 dplyr
利用 data.table
中的 rleid
library(dplyr)
df1 %>%
group_by(grp = rleid(TYPE_OF_PROMOTION)) %>%
mutate(counter2 = case_when(is.na(TYPE_OF_PROMOTION) ~ NA_integer_,
TRUE ~ row_number())) %>%
ungroup %>%
select(-grp)
或使用 base R
和 rle
with(df1, with(rle(!is.na(TYPE_OF_PROMOTION)),
sequence(lengths) * rep(NA^!values, lengths)))
#[1] NA 1 2 3 NA NA NA 1 2 NA
数据
df1 <- structure(list(Week = 11:20, TYPE_OF_PROMOTION = c(NA, "B", "B",
"B", NA, NA, NA, "B", "B", NA), counter = c(NA, 1L, 2L, 3L, NA,
NA, NA, 1L, 2L, NA)), class = "data.frame", row.names = c("11",
"12", "13", "14", "15", "16", "17", "18", "19", "20"))
我读了很多书,测试了很多书,但都没有成功。 我希望为每个组创建一个计数器,但是这个 coutner 会在每次出现一个组时重新启动(即使它 "reappears")。
示例:
我需要一个 seq_along 每个 TYPE_OF_PROMOTION
重新启动每个组外观。
结果应该像 counter
由于促销 B 在第 18 周重新出现但是是新出现 - 重新启动计数器。
如果该解决方案也适用于 NA - 好的,我只是做了一个快速演示。
Week TYPE_OF_PROMOTION counter
11 11 <NA> NA
12 12 B 1
13 13 B 2
14 14 B 3
15 15 <NA> NA
16 16 <NA> NA
17 17 <NA> NA
18 18 B 1
19 19 B 2
20 20 <NA> NA
这里有一个 data.table
的选项。将 'data.frame' 转换为 'data.table' (setDT(df1)
),按 'TYPE_OF_PROMOTION' 的 运行-length-id 分组,创建行序列 (seq_len(.N)
) 乘以在 'TYPE_OF_PROMOTION' 中具有 NA
的值以创建 'counter' 列
library(data.table)
setDT(df1)[, counter2 := seq_len(.N) * NA^is.na(TYPE_OF_PROMOTION),
by = rleid(TYPE_OF_PROMOTION)]
df1
# Week TYPE_OF_PROMOTION counter counter2
# 1: 11 <NA> NA NA
# 2: 12 B 1 1
# 3: 13 B 2 2
# 4: 14 B 3 3
# 5: 15 <NA> NA NA
# 6: 16 <NA> NA NA
# 7: 17 <NA> NA NA
# 8: 18 B 1 1
# 9: 19 B 2 2
#10: 20 <NA> NA NA
或 dplyr
利用 data.table
rleid
library(dplyr)
df1 %>%
group_by(grp = rleid(TYPE_OF_PROMOTION)) %>%
mutate(counter2 = case_when(is.na(TYPE_OF_PROMOTION) ~ NA_integer_,
TRUE ~ row_number())) %>%
ungroup %>%
select(-grp)
或使用 base R
和 rle
with(df1, with(rle(!is.na(TYPE_OF_PROMOTION)),
sequence(lengths) * rep(NA^!values, lengths)))
#[1] NA 1 2 3 NA NA NA 1 2 NA
数据
df1 <- structure(list(Week = 11:20, TYPE_OF_PROMOTION = c(NA, "B", "B",
"B", NA, NA, NA, "B", "B", NA), counter = c(NA, 1L, 2L, 3L, NA,
NA, NA, 1L, 2L, NA)), class = "data.frame", row.names = c("11",
"12", "13", "14", "15", "16", "17", "18", "19", "20"))