【问题标题】:delete rows based on type of previous rows根据先前行的类型删除行
【发布时间】:2019-01-03 13:53:45
【问题描述】:

我正在尝试根据先前行的类型删除行。如果我的 data.frame 看起来像:

|日期 |时间 |类型 |毛额 |发件人电子邮件 |收件人邮箱 | |2018.07.12 |12:45:13 |网站支付 | 30 | aaa@customer.com | admin@site.com | |2018.07.21 |16:19:34 |网站支付 | 30 | bbb@customer.com | admin@site.com | |2018.07.22 |18:21:17 |付款退款 | -30 | admin@site.com | bbb@custom.com | |2018.07.24 |07:10:00 |网站支付 | 30 | bbb@customer.com | admin@site.com | |2018.08.17 |15:17:40 |网站支付 | 30 | ccc@custom.com | admin@site.com |

我想删除已退款的交易。

|日期 |时间 |类型 |毛额 |发件人电子邮件 |收件人邮箱 | |2018.07.12 |12:45:13 |网站支付 | 30 | aaa@customer.com | admin@site.com | |2018.07.24 |07:10:00 |网站支付 | 30 | bbb@customer.com | admin@site.com | |2018.08.17 |15:17:40 |网站支付 | 30 | ccc@custom.com | admin@site.com |

任何帮助将不胜感激!

【问题讨论】:

  • 如果付款和退款之间可以有其他线路,唯一的解决方法是如果您有一个付款 ID,付款和退款线路将共享。如果没有ID,那么是不是付款行的发件人邮箱应该与退款行的收件人邮箱相对应呢?但是同一封电子邮件可以有几笔付款,因此至少也应该检查总金额。 (“总”列?)

标签: r dataframe


【解决方案1】:

我们可以使用grep

i1 <- grep('Refund', df1$Type)
i2 <- c(i1, i1-1)
df1[setdiff(seq_len(nrow(df1)), i2),]
#        Date     Time            Type Gross      Sender_email Receiver_email
#1 2018.07.12 12:45:13 Website Payment    30  aaa@customer.com admin@site.com
#4 2018.07.24 07:10:00 Website Payment    30 bbb@@customer.com admin@site.com
#5 2018.08.17 15:17:40 Website Payment    30    ccc@custom.com admin@site.com

更新

如果付款和退款之间有其他线路

i1 <- grep('Refund', df1$Type)
out <- do.call(rbind, Map(function(i, j) {
       x <- df1[i:j, ]
       i2 <- grep('Website Payment', x$Type)
       x[setdiff(rownames(x), c(j, i2)), ] }, c(1, i1[-length(i1)] + 1), i1))

【讨论】:

  • 不明白为什么 OP 的预期输出中缺少第二行 :-(
  • 谢谢!与上面的示例不同,如果付款和退款之间有另一条线怎么办?
  • 是的,我知道。您的答案非常清晰和简单,但我想知道如何在更一般的情况下使用它。 :)
  • 进一步考虑这个问题,我可以随时使用您的解决方案,使用提取和排序。谢谢。
  • @Mimi 如果您可以使用相关示例更新您的帖子,那将会很有帮助
【解决方案2】:

我有一个简单的解决方案,它可能不够优雅和快速。 在您的示例中,您可以先搜索退款发生的位置,然后查找退款的人,最后删除这些行。 代码可能是这样的:

delete_refund=function(transaction_matrix){

  #find in which row refund happens
  index_refund=which(transaction_matrix[ , "Gross"]<0);

  #find who receive refund
  refunded=transaction_matrix[index_refund, "Receiver_email"];

  #for each one refunds, find what they purchase before refund
  all_refund_purchase=vector();
  for (row in index_refund) {
    one_purchase=which((transaction_matrix[1:row,"Gross"]==
      abs(transaction_matrix[row,"Gross"])) &                
      (transaction_matrix[1:row,"Sender_email"]==
      transaction_matrix[row,"Receiver_email"]));
    #one may buy several things at the same value and refund part of them, so length of one_purchase may be greater than 1
    one_purchase=one_purchase[!(one_purchase %in% all_refund_purchase)];
    #one may has many refunds, record those which haven't been captured in all_refund_purchase
    all_refund_purchase=c(all_refund_purchase, 
      one_purchase[length(one_purchase)])
    #when some one bought several things at the same value
  }

  return(transaction_matrix[c(-index_refund, -all_refund_purchase), ]);
}

由于缺乏数据样本,我在我创建的一个简单示例中对其进行了测试。

df=data.frame(date=1:4, Gross=c(30,30,-30,30), 
    Sender_email=c('bbb@customer.com','ccc@customer.com',
      'admin@site.com','bbb@customer.com'),
    Receiver_email=c('admin@site.com','admin@site.com',
      'bbb@customer.com','admin@site.com'), 
    stringsAsFactors = FALSE);

  date Gross     Sender_email   Receiver_email
1    1    30 bbb@customer.com   admin@site.com
2    2    30 ccc@customer.com   admin@site.com
3    3   -30   admin@site.com bbb@customer.com
4    4    30 bbb@customer.com   admin@site.com

结果是

  date Gross     Sender_email Receiver_email
2    2    30 ccc@customer.com admin@site.com
4    4    30 bbb@customer.com admin@site.com

满足了发帖人的需求。

【讨论】:

  • 我认为你的代码有一点错误。 '#delete rows of refunding' 和 '#delete rows of those who received return pays' 都使用“neat_matrix”。所以退款代码(Gross>=0)无效。
  • @Mimi 很抱歉犯了这个错误,我已经颠倒了代码。
  • @Mimi 但是我仍然有一些我以前没有意识到的问题。我注意到在您的数据中,我看到 bbb@@customer.com 和双 @ 和 bbb@customer.com。我有点困惑。
  • 哦,打错了。我很抱歉。我的数据不清楚,所以你的代码没有得到我期望的结果。根据你的代码,bbb@customer.com'的交易细节被删除。该人(bbb)购买了一件物品,然后退款,然后又重新购买。
  • @Mimi 我又把代码倒过来做了一个基本的测试,现在应该是你所期望的,虽然看起来有点复杂。
猜你喜欢
  • 2021-04-11
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多