【发布时间】:2021-07-08 22:21:13
【问题描述】:
假设以下数据:
set.seed(1)
df <- data.frame(name = rep(letters[1:3], 5),
condition = sample(0:1 , 15, replace = TRUE))
df
name condition
1 a 0
2 b 1
3 c 0
4 a 0
5 b 1
6 c 0
7 a 0
8 b 0
9 c 1
10 a 1
11 b 0
12 c 0
13 a 0
14 b 0
15 c 0
我现在想在按名称分组后逐行浏览我的数据框,当满足条件时,我想在名称列中添加一个星号 (*)。如果不满足条件,我想用之前的名称值替换名称值。
- 所以在第 2 行,我想将“b”更改为“b*”。
- 在第 5 行中,我想将“b*”(因为我们已经将第 2 行更改为)更改为“b**”。
- 在第8行中,条件不满足,所以我只想保留之前的b值,即“b**”。
我认为我可以通过使用简单的case_when 解决方案来超越 R,但显然我在下面的代码中失败了。有什么想法吗?
library(tidyverse)
df %>%
group_by(name) %>%
mutate(helper_id = 1:n(),
name = case_when(condition == 1 & helper_id == 1 ~ paste0(name, "*"),
condition != 1 & helper_id == 1 ~ name,
condition == 1 & helper_id != 1 ~ paste0(lag(name), "*"),
condition != 1 & helper_id != 1 ~ lag(name))) %>%
ungroup()
此代码在满足条件时添加一个星号,但如果不满足条件,则不采用前一个/滞后名称值。我想问题是case_when 没有逐行遍历整个事情。
【问题讨论】:
-
我猜你可能想在分组
df %>% mutate(name_lag = lag(name)之前创建一个滞后列并在 case_when 中使用它 -
对不起。忘记复制 set.seed。已添加。
-
你想要
df %>% group_by(name) %>% mutate(res = paste0(name, Reduce(paste0, ifelse(condition == 1, "*", ""), accumulate = TRUE)))吗? -
可能你需要
cummax -
@deschen 你需要
df %>% group_by(name) %>% mutate(cumsum_condition = cumsum(condition)) %>% mutate(name1 = str_c(name, strrep("*", cumsum_condition)))