R cumsum 与 if 条件
R cumsum with if condition
假设我有这个数据框
df <-
data.frame(
id = seq(1, 8),
type = c("NEW", "OLD", "OLD", "NEW", "OLD", "NEW", "NEW", "OLD")
)
我想为每个 TYPE OLD 组创建“段”,因此结果是这样的 - 每个段都用订单号标记,请注意前两个旧类型有 1 作为段,第二段是标记为 2.
df <-
data.frame(
id = seq(1, 8),
type = c("NEW", "OLD", "OLD", "NEW", "OLD", "OLD", "NEW", "OLD"),
segment = c(0, 1, 1, 0, 2, 2, 0, 3)
)
但我在 R 中实现这个时遇到了问题。我可以为类型段创建 if else,我想我需要通过 cumsum 函数来完成,但我还没有找到方法。
mutate(
segment = if_else(type == "NEW", 0, 1)
)
这是一种使用行号差异方法的方法。这种方法通常用于数据库中的间隙和孤岛问题,这基本上也是这个 R 问题。
df$segment <- ifelse(df$type == "OLD", df$id - cumsum(df$type == "OLD"), 0)
df
id type y segment
1 1 NEW 1 0
2 2 OLD 1 1
3 3 OLD 1 1
4 4 NEW 2 0
5 5 OLD 2 2
6 6 OLD 2 2
7 7 NEW 3 0
8 8 OLD 3 3
这里的方法是区分整个数据帧上的序列和仅 OLD
条目上的序列。考虑以下差异:
1 2 3 4 5 6 7 8
0 1 2 2 3 4 4 5
---------------
1 1 1 2 2 2 3 3
那么,我们只保留上述差分属于OLD
的值。
cumsum
的另一种方法:
df %>% mutate(
segment = cumsum(lag(type, 1, 'NEW') == 'NEW' & type == 'OLD') * (type == 'OLD'))
# id type segment_expected segment
# 1 1 NEW 0 0
# 2 2 OLD 1 1
# 3 3 OLD 1 1
# 4 4 NEW 0 0
# 5 5 OLD 2 2
# 6 6 OLD 2 2
# 7 7 NEW 0 0
# 8 8 OLD 3 3
这里使用的df
是:
df <-data.frame(
id = seq(1, 8),
type = c("NEW", "OLD", "OLD", "NEW", "OLD", "OLD", "NEW", "OLD"),
segment_expected = c(0, 1, 1, 0, 2, 2, 0, 3))
基础 R 使用 rle
-
transform(df, segment = with(rle(type == 'NEW'),
rep(cumsum(values) * as.integer(!values), lengths)))
# id type segment
#1 1 NEW 0
#2 2 OLD 1
#3 3 OLD 1
#4 4 NEW 0
#5 5 OLD 2
#6 6 NEW 0
#7 7 NEW 0
#8 8 OLD 3
假设我有这个数据框
df <-
data.frame(
id = seq(1, 8),
type = c("NEW", "OLD", "OLD", "NEW", "OLD", "NEW", "NEW", "OLD")
)
我想为每个 TYPE OLD 组创建“段”,因此结果是这样的 - 每个段都用订单号标记,请注意前两个旧类型有 1 作为段,第二段是标记为 2.
df <-
data.frame(
id = seq(1, 8),
type = c("NEW", "OLD", "OLD", "NEW", "OLD", "OLD", "NEW", "OLD"),
segment = c(0, 1, 1, 0, 2, 2, 0, 3)
)
但我在 R 中实现这个时遇到了问题。我可以为类型段创建 if else,我想我需要通过 cumsum 函数来完成,但我还没有找到方法。
mutate(
segment = if_else(type == "NEW", 0, 1)
)
这是一种使用行号差异方法的方法。这种方法通常用于数据库中的间隙和孤岛问题,这基本上也是这个 R 问题。
df$segment <- ifelse(df$type == "OLD", df$id - cumsum(df$type == "OLD"), 0)
df
id type y segment
1 1 NEW 1 0
2 2 OLD 1 1
3 3 OLD 1 1
4 4 NEW 2 0
5 5 OLD 2 2
6 6 OLD 2 2
7 7 NEW 3 0
8 8 OLD 3 3
这里的方法是区分整个数据帧上的序列和仅 OLD
条目上的序列。考虑以下差异:
1 2 3 4 5 6 7 8
0 1 2 2 3 4 4 5
---------------
1 1 1 2 2 2 3 3
那么,我们只保留上述差分属于OLD
的值。
cumsum
的另一种方法:
df %>% mutate(
segment = cumsum(lag(type, 1, 'NEW') == 'NEW' & type == 'OLD') * (type == 'OLD'))
# id type segment_expected segment
# 1 1 NEW 0 0
# 2 2 OLD 1 1
# 3 3 OLD 1 1
# 4 4 NEW 0 0
# 5 5 OLD 2 2
# 6 6 OLD 2 2
# 7 7 NEW 0 0
# 8 8 OLD 3 3
这里使用的df
是:
df <-data.frame(
id = seq(1, 8),
type = c("NEW", "OLD", "OLD", "NEW", "OLD", "OLD", "NEW", "OLD"),
segment_expected = c(0, 1, 1, 0, 2, 2, 0, 3))
基础 R 使用 rle
-
transform(df, segment = with(rle(type == 'NEW'),
rep(cumsum(values) * as.integer(!values), lengths)))
# id type segment
#1 1 NEW 0
#2 2 OLD 1
#3 3 OLD 1
#4 4 NEW 0
#5 5 OLD 2
#6 6 NEW 0
#7 7 NEW 0
#8 8 OLD 3