首页 文章

基于组中条件和的mutate

提问于
浏览
0

假设我有一个这样的数据帧:

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 回答

  • 0

    我很难跟踪你想要改变的值 .

    但是当我有一个需要在序列中进行的多个条件或决策时,我使用循环和一系列if语句来遍历数据框 . 我更喜欢 while 循环,因此在示例中使用了's what I'll .

    counter <- 1
    stopper <- nrow(df)
    while (counter <= stopper) {
    
     fac1 <- df$Fac1[counter1]
    
     if (fac1 == 'e') {
    
      if ([INSERT NEXT CONDITION]) #Change whichever value your trying to change using the counter to reference the correct row.
      else #Change whichever value your trying to change using the counter to reference the correct row.
    
     }
    
    counter <- counter + 1
    }
    

    对我来说,简化代码使我更容易跟踪正在做出的决策 . 它还允许难以使函数使用的复杂决策 .

  • 0

    我能够使用此代码获得所需的结果 . 我创建了一个包含测试结果的新列,用于替换Fac2的值,这不是完全必要的,但使其更具可读性和可调试性 . 关键是使用 first(na.omit()) 从同一组中满足条件的另一行获取值 .

    result <- df %>% group_by(ID) %>% 
      mutate(Max_bc_Val = ifelse(Val2 == max(ifelse(Fac1 %in% c("b","c"),
                                              Val2,0)),
                          ifelse(Fac1 %in% c("b","c"),
                                 as.character(Fac2),NA),NA)) %>% 
      mutate(Fac2 = case_when(
        Fac1 == "e" ~ ifelse(is.na(first(na.omit(Max_bc_Val))),
                             NA_character_,
                             first(na.omit(Max_bc_Val))),
        TRUE ~ as.character(Fac2)))
    

    这有效,但似乎不是最好的解决方案 . 还有其他想法吗?

相关问题