【问题标题】:Columns generation for levels from factor variables by aggregating conditionally using group by in R通过在 R 中使用 group by 有条件地聚合,从因子变量中生成级别的列
【发布时间】:2023-03-29 16:39:01
【问题描述】:

对于下面的数据框,我正在尝试从 FactorCol1 有条件地创建八个额外的列 Last1Col7activ 到 Last10Col7inactive:

library(tidyverse)
Data_Frame <- data.frame(Col1 = c("A1", "A1", "A1", "A2", "A2", "A2", "A3", "A3", "A3"),
                         
                         Col2 = c("2011-03-11", "2014-08-21", "2016-01-17", "2017-06-30", "2018-07-11", "2018-11-28", "2019-09-04", "2020-02-29", "2020-07-12"),
                         
                         Col3 = c("2018-10-22", "2019-05-24", "2020-12-25", "2018-10-12", "2019-09-24", "2020-12-19", "2018-10-22", "2019-06-14", "2020-12-20"),
                         
                         Col4 = c(4, 2, 2, 1, 4, 4, 4, 4, 4),
                         
                         Col5 = c(7, 6, 3, 1, 3, 2, 5, 1, 2),
                         
                         FactorCol1 = c("active", "inactive", "inactive", "active", "active", "inactive", "inactive", "active", "inactive"),
                         
                         FactorCol2 = c("Level2", "Level2", "Level3", "Level1", "Level3", "Level1", "Level2", "Level1", "Level3"))

Data_Frame$Col1 <- as.factor(Data_Frame$Col1)
Data_Frame$Col2 <- as.Date(Data_Frame$Col2)
Data_Frame$Col3 <- as.Date(Data_Frame$Col3)
Data_Frame$FactorCol1 <- as.factor(Data_Frame$FactorCol1)
Data_Frame$FactorCol2 <- as.factor(Data_Frame$FactorCol2)

Data_Frame <- Data_Frame %>% group_by(Col1) %>% mutate(Col6 = lubridate::time_length(lubridate::interval(Col2, max(Col3)), "years"))
Data_Frame <- Data_Frame %>% group_by(Col1) %>% dplyr::mutate(Col7 = ifelse(Col6 <= 1, 1, ifelse(Col6 >1 & Col6 <=2, 2, ifelse(Col6 >2 & Col6 <=5, 5, ifelse(Col6 >5 & Col6 <=10, 10, 11)))))

Data_Frame <- Data_Frame %>% group_by(Col1) %>% dplyr::mutate(Col8 = ifelse(FactorCol1 == 'active', 1, 0))
Data_Frame <- Data_Frame %>% group_by(Col1) %>% dplyr::mutate(Col9 = ifelse(FactorCol1 == 'inactive', 1, 0))

Data_Frame <- as.data.frame(Data_Frame)

Data_Frame <- map_dfc(c(1, 2, 5, 10), ~ Data_Frame %>%
          group_by(Col1) %>% 
          transmute(!! sprintf("Last%dCol7active", .x) := ifelse(((Col7 <= .x)), sum(Col8 == 1),0),
                    !! sprintf("Last%dCol7inactive", .x) := ifelse(((Col7 <= .x)), sum(Col9 == 1),0)) %>% 
          ungroup %>%
          select(-Col1)) %>% 
          bind_cols(Data_Frame, .)

在上面,

Col6:每组内max(Col3)和Col2之间的时间差

Col7:Col6 中的值的 (

Col8:FactorCol1 中的活动元素设置为 1

Col9:FactorCol1 中的非活动元素设置为 1

Last1Col7active:在每个组内(Col1 中的 A1 到 A3),FactorCol1 中的活动元素数量

Last1Col7inactive:在每个组中,FactorCol1 中的非活动元素数量

Last5Col7active:在每个组内(Col1 中的 A1 到 A3),FactorCol1 中的活动元素数在 Col7 中

Last5Col7inactive:在每个组中,FactorCol1 中的非活动元素数在 Col7 中

Last10Col7active:在每个组内(Col1 中的 A1 到 A3),FactorCol1 中的活动元素数

Last10Col7inactive:在每个组内,FactorCol1 中的非活动元素数在 Col7 中

预期结果是:

但是,输出是:

出了什么问题?而且,有没有一种方法可以自动生成这些列,而无需在 transmute 中输入关卡的名称?

【问题讨论】:

    标签: r dplyr group-by conditional-statements aggregate


    【解决方案1】:

    您不需要ifelse。这只是您的功能的一个小简化:

    Data_Frame <- map_dfc(c(1, 2, 5, 10), ~ Data_Frame %>%
                              group_by(Col1) %>% 
                              transmute(!! sprintf("Last%dCol7active", .x) := sum(Col8[Col7 <= .x]),
                                        !! sprintf("Last%dCol7inactive", .x) := sum(Col9[Col7 <= .x])) %>% 
                              ungroup %>%
                              select(-Col1)) %>% 
        bind_cols(Data_Frame, .)
      Col1       Col2       Col3 Col4 Col5 FactorCol1 FactorCol2      Col6 Col7 Col8 Col9 Last1Col7active Last1Col7inactive Last2Col7active Last2Col7inactive Last5Col7active Last5Col7inactive
    1   A1 2011-03-11 2018-10-22    4    7     active     Level2 9.7917808   10    1    0               0                 0               0                 0               0                 1
    2   A1 2014-08-21 2019-05-24    2    6   inactive     Level2 6.3452055   10    0    1               0                 0               0                 0               0                 1
    3   A1 2016-01-17 2020-12-25    2    3   inactive     Level3 4.9371585    5    0    1               0                 0               0                 0               0                 1
    4   A2 2017-06-30 2018-10-12    1    1     active     Level1 3.4712329    5    1    0               0                 0               0                 0               2                 1
    5   A2 2018-07-11 2019-09-24    4    3     active     Level3 2.4410959    5    1    0               0                 0               0                 0               2                 1
    6   A2 2018-11-28 2020-12-19    4    2   inactive     Level1 2.0575342    5    0    1               0                 0               0                 0               2                 1
    7   A3 2019-09-04 2018-10-22    4    5   inactive     Level2 1.2931507    2    0    1               1                 1               1                 2               1                 2
    8   A3 2020-02-29 2019-06-14    4    1     active     Level1 0.8060109    1    1    0               1                 1               1                 2               1                 2
    9   A3 2020-07-12 2020-12-20    4    2   inactive     Level3 0.4410959    1    0    1               1                 1               1                 2               1                 2
      Last10Col7active Last10Col7inactive
    1                1                  2
    2                1                  2
    3                1                  2
    4                2                  1
    5                2                  1
    6                2                  1
    7                1                  2
    8                1                  2
    9                1                  2
    

    【讨论】:

    • 感谢指正,有没有办法根据 FactorCol1 的水平自动生成列?
    • 我不确定你的目标。我会说一个嵌套的map_dfc,比如map_dfc(c(1, 2, 5, 10), function(.x) map_dfc(levels(Data_Frame$FactorCol1), function(.y) Data_Frame %&gt;% group_by(Col1) %&gt;% transmute(!! sprintf("Last%dCol7%s", .x, .y) := sum(Col8[Col7 &lt;= .x]), !! sprintf("Last%dCol7%s", .x, .y) := sum(Col9[Col7 &lt;= .x])) ...?
    • 我不确定您的评论中的Data_Frame 是什么(您是问题的哪一步?),那么K 是什么?也许这是另一个问题的主题......
    猜你喜欢
    • 2021-10-12
    • 1970-01-01
    • 2017-07-27
    • 2018-06-24
    • 1970-01-01
    • 2018-08-17
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多