【问题标题】:How to dynamically conditionally filter rows in R dataframe如何动态有条件地过滤 R 数据框中的行
【发布时间】:2018-01-03 16:20:06
【问题描述】:

假设我有一个如下所示的有序数据框:

df <- data.frame(customer = c('cust1','cust1','cust2','cust3','cust3'),
start_month = as.Date(c('2016-03-01','2017-08-01','2016-03-01','2017-07-01','2017-10-01')),
price = c(29,29,59,99,59),
end_month = as.Date(c('2017-08-01',NA,'2017-09-01','2017-09-01',NA)));

如何在 R 中编写具有以下业务规则的脚本:如果客户在同一个月结束并开始,并且价格没有变化,则删除最新交易。否则,保留交易。生成的数据框如下所示:

new_df <- data.frame( customer = c('cust1','cust2','cust3','cust3'),
start_date = as.Date(c('2016-03-01','2016-03-01','2017-07-01','2017-10-01')),
price = c(29,59,99,59),
end_date = as.Date(c(NA,'2017-09-01','2017-09-01',NA)));

在此示例中,cust1 的 2017-08-01 被忽略并过滤掉,因为价格与他们之前的交易相同。但是由于价格不同,cust3的交易被保留了。

如何在 R 中做到这一点?

【问题讨论】:

    标签: r conditional filtering rowwise


    【解决方案1】:
    library(dplyr)
    df <- df %>% group_by(customer) %>% mutate(change = lag(price) - price)
    
    > df
    # A tibble: 5 x 5
    # Groups:   customer [3]
      customer start_month price  end_month change
        <fctr>      <date> <dbl>     <date>  <dbl>
    1    cust1  2016-03-01    29 2017-08-01     NA
    2    cust1  2017-08-01    29         NA      0
    3    cust2  2016-03-01    59 2017-09-01     NA
    4    cust3  2017-07-01    99 2017-09-01     NA
    5    cust3  2017-10-01    59         NA     40
    

    客户的第一个条目始终是 NA,我们将保留这些条目。我们将删除价格没有变化的行:

    df <- df %>% filter(is.na(change) | change != 0)
    
    > df
    # A tibble: 4 x 5
    # Groups:   customer [3]
      customer start_month price  end_month change
        <fctr>      <date> <dbl>     <date>  <dbl>
    1    cust1  2016-03-01    29 2017-08-01     NA
    2    cust2  2016-03-01    59 2017-09-01     NA
    3    cust3  2017-07-01    99 2017-09-01     NA
    4    cust3  2017-10-01    59         NA     40
    

    多合一命令:

    library(dplyr)
    df <-
      df %>% 
      group_by(customer) %>% 
      mutate(change = lag(price) - price) %>% 
      filter(is.na(change) | change != 0)
    

    编辑:

    我忘记检查日期是否更改:

    library(dplyr)
    df <-
      df %>% 
      group_by(customer) %>% 
      mutate(change = lag(price) - price) %>%
      mutate(date_change = lag(end_month) - start_month) %>%
      filter((is.na(change) | change != 0) | (is.na(date_change) | date_change != 0))
    

    这将保留每个第一个条目并删除开始日期与上一个结束日期相同且价格未更改的行。

    【讨论】:

    • 啊,是的。我懂了。这是有道理的。我看到我需要将 dplyr 用作“做这个,然后做这个,然后做这个”的思维方式。你说这对吗?
    • 如果我想删除与该客户相关的每笔交易,而不是保留一笔,该怎么办?过滤器似乎就像它保留的 SQL 中的 SELECT 一样。除了使用相反的逻辑运算符之外,如何删除符合我想要的条件的内容?
    • 这种想法是正确的 :) 除了使用过滤器并告诉它您要保留哪些行之外,我不知道有什么方法可以删除某些行。在这个问题中,他们使用了anti_join(),也许这值得一看:stackoverflow.com/questions/45661377/…。如果您想删除客户 3 的每笔交易,您可以这样做:df %&gt;% filter(customer != "cust3")
    猜你喜欢
    • 2021-06-20
    • 2019-07-27
    • 2020-04-12
    • 2018-07-29
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    相关资源
    最近更新 更多