假设我有一个这样的数据帧:
set.seed(1)
n <- 20
df <- data.frame(ID = sample(1:5, n, replace = TRUE),
Fac1 = sample(letters[1:5], n, replace = TRUE),
Fac2 = sample(LETTERS[10:15], n, replace = TRUE),
Val1 = sample(1:10, n, replace = TRUE)) %>%
arrange(ID) %>% group_by(ID,Fac1) %>%
summarise(Val1 = sum(Val1),Fac2 = first(Fac2)) %>%
group_by(ID,Fac2) %>%
mutate(Val2 = sum(Val1))
df
ID Fac1 Val1 Fac2 Val2
1 1 b 9 N 9
2 1 c 9 O 9
3 2 a 4 K 4
4 2 b 10 M 18
5 2 c 4 L 4
6 2 d 8 M 18
7 2 e 10 N 10
8 3 d 14 N 14
9 4 b 8 L 22
10 4 c 14 L 22
11 4 d 9 K 9
12 4 e 6 N 6
13 5 a 13 M 13
14 5 b 3 N 3
ID是分组变量 . Fac1值为e的行应将Fac2值更改为与Fac1为b或c的组中的另一行相同,如果大于20,则将两行的Val 2相加 . (I 've simplified this to the point where you probably don' t得到原因但只是和我一起工作) .
这是我到目前为止所尝试的:
result <- df %>% group_by(ID) %>%
mutate(Fac2 = case_when(
Fac1 == "e" &
sum(Val2,ifelse(Fac1 %in% c("b","c"), Val2, 0)) > 20 ~
ifelse(sum(Val2,ifelse(Fac1 %in% c("b","c"),Val2,0)) > 20,
as.character(Fac2),
NA_character_),
TRUE ~ as.character(Fac2)
))
它不能正常工作,因为它将组中Val2的第一个值相加,而不是仅当Fac1为b或c时才这样做 .
有任何想法吗?
添加所需的结果:
ID Fac1 Val1 Fac2 Val2
1 1 b 9 N 9
2 1 c 9 O 9
3 2 a 4 K 4
4 2 b 10 M 18
5 2 c 4 L 4
6 2 d 8 M 18
7 2 e 10 M 10 **Changed to M b/c row 4 is M and 10 + 18 > 20
8 3 d 14 N 14
9 4 b 8 L 22
10 4 c 14 L 22
11 4 d 9 K 9
12 4 e 6 L 6 **Changed to L b/c row 10 is L and 6 + 22 > 20
13 5 a 13 M 13
14 5 b 3 N 3
2 回答
我很难跟踪你想要改变的值 .
但是当我有一个需要在序列中进行的多个条件或决策时,我使用循环和一系列if语句来遍历数据框 . 我更喜欢
while
循环,因此在示例中使用了's what I'll .对我来说,简化代码使我更容易跟踪正在做出的决策 . 它还允许难以使函数使用的复杂决策 .
我能够使用此代码获得所需的结果 . 我创建了一个包含测试结果的新列,用于替换Fac2的值,这不是完全必要的,但使其更具可读性和可调试性 . 关键是使用
first(na.omit())
从同一组中满足条件的另一行获取值 .这有效,但似乎不是最好的解决方案 . 还有其他想法吗?