dplyr:根据不同条件分组,然后返回top n

Posted

技术标签:

【中文标题】dplyr:根据不同条件分组,然后返回top n【英文标题】:Dplyr: Group by and then return top n based on different conditons 【发布时间】:2021-11-15 16:49:23 【问题描述】:

我一直在尝试解决对我的数据进行分组(按贷款编号)的问题,然后根据某一列(这里是过滤器列)的最高或最低值返回每组一行不同的条件。我意识到我不能使用 ifelse 来做我想做的事情,但是其他示例使用了 if 和 else(因此我尝试了)。在此过程中,我遇到了各种各样的错误。任何帮助以及澄清问题将不胜感激

Example data
Loan_Number <- c(100,100,100,100,200,200,200,200,300,300,300,300)
Principal_Remaining <- c(50,50,50,50,5,5,0,0,10,10,10,10)
Principal_In_Arrears <- c(50,50,50,50,0,0,0,0,0,10,10,10)
Write_off_Number <- c(10,10,10,10, 0,0,0,0,0,0,0,0)
Filter <- c (1,2,3,4,5,6,7,8,9,10,11,12)

outcome <- as.data.frame(cbind(Loan_Number,Principal_In_Arrears, Principal_Remaining, Write_off_Number, Filter))

我对代码的最后一次尝试是

    hope <- outcome %>%
    group_by(Loan_Number) %>% 
          if(Principal_Remaining == 0)  top_n( -1, wt = Filter) else
             if(Principal_In_Arrears == 0) top_n( -1, wt = Filter) else
               if(Write_off_Number >= 0) top_n( 1, wt = Filter) else top_n( -1, wt = 
                  Filter)))

这个想法是,如果没有本金,那么我想要一个特定的价值,如果有本金,我必须检查贷款是否拖欠或已注销。

NB 为了确认确切的要求,我需要避免考虑不符合条件的行。例如,对于贷款 200,返回的记录应返回第 7 行(本金为 0 的最低月份)。第一个答案没有这样做。此外,贷款 300 应该返回第 10 行(条件应该是!= 0 和过滤器的最小值),它在第一个月拖欠。贷款 1 应该只返回第 1 行。

【问题讨论】:

我有点不确定你想要的结果是什么。你能用伪代码写出你想要的条件,和/或提供一些预期的输出吗? 下面提供的答案是要发生的事情。 我在这里造成了一些混乱,抱歉。为了澄清事情,我改变了最初的 DF。 Loan 300 现在拖欠了创纪录的 10 笔。我实际上需要最小值,所以它现在应该返回第 10 行以获得贷款 300。 【参考方案1】:

您可以使用case_whenslice 来选择每个Loan_Number 的行。

library(dplyr)

outcome %>%
  group_by(Loan_Number) %>%
  slice(case_when(any(Principal_Remaining == 0) ~ which.max(Filter), 
                  any(Principal_In_Arrears == 0) ~ which.min(Filter), 
                  any(Write_off_Number >= 0) ~ which.max(Filter), 
                  TRUE ~ which.min(Filter))) %>%
  ungroup
  

#  Loan_Number Principal_In_Arrears Principal_Remaining Write_off_Number Filter
#        <dbl>                <dbl>               <dbl>            <dbl>  <dbl>
#1         100                   50                  50               10      4
#2         200                    0                   0                0      8
#3         300                   10                  10                0     12

【讨论】:

这个答案很接近但不太正确。我已经对原始问题进行了一些调整,以解释应该发生什么【参考方案2】:

在这一点上这是可行的,但我不是 100% 它会随着其他组合的发展而继续发挥作用

hope <- outcome %>%
  group_by(Banjo_Loan_No) %>%
  dplyr::slice(case_when(any(Principal_Remaining == 0)  ~ which.min(abs(filter*Principal_Remaining)), 
                         any(Principal_in_Arrears == 0) ~  which.max(abs(filter*Principal_in_Arrears > 0)), 
                         any(Write_Off_Date != "1016-01-01") ~ which.max(filter), 
                         TRUE ~ which.min(filter))) 

【讨论】:

以上是关于dplyr:根据不同条件分组,然后返回top n的主要内容,如果未能解决你的问题,请参考以下文章

R语言dplyr包的top_n函数返回dataframe或tibble的前N行数据dplyr包的top_frac函数返回dataframe或tibble的前百分之N(N%)的数据

MySQL:如何查询出每个分组中的 top n 条记录?

dplyr summarise :在循环中按多个变量分组并将结果添加到同一数据框中

r - 按日期过滤,按条件分组

根据不同的条件对两个不同的列进行分组和求和

使用 dplyr 嵌套或分组两个变量,然后对数据执行 Cronbach 的 alpha 函数或其他统计