计算R中每月的记录数

问题描述

鉴于商户ID,卡号和日期,我需要计算每月与每个商户ID相关联的卡号的数量。到目前为止,我只能计算每个商户ID的卡号数量,但现在还不能使用以下代码每月计算它:

HitsCounter <- summarise(group_by(df,MerchantID),HitsTotal = n_distinct(CardNum))

可复制的数据:

MerchantID <- c('1234,'1234','1234')
CardNum <- c('1abc1','1abc1','2xyz2','3ijk3')
Date <- c('2020-05-07','2020-05-07','2019-10-12','2019-10-25')
df <- data.frame(MerchantID,CardNum,Date)

将HitsCounter合并到数据框df中会得到什么:

MerchantID  CardNum     Date        HitsTotal
  1234       1abc1   2020-05-07         3
  1234       1abc1   2020-05-07         3
  1234       2xyz2   2019-10-12         3
  1234       3ijk3   2019-10-25         3
 

预期的输出数据:

MerchantID  CardNum     Date        HitsPerMonth
  1234       1abc1   2020-05-07          2
  1234       1abc1   2020-02-07          1
  1234       2xyz2   2020-05-12          2
  1234       3ijk3   2019-10-25          1
  1234       3ijk3   2019-10-01          1      

请注意,逻辑上应该完全忽略任何重复的CardNumber,即使在不同的月份也是如此,因为每个唯一的CardNumber都会计算一次“命中”。

简单地说,它应该回答以下问题:

在同一个月内用同一商家ID交易过多少个唯一卡号?

解决方法

您可以从日期中提取年月值,并为每个CardNumMerchantID计算唯一的month值。

library(dplyr)

df %>%
  mutate(Date = as.Date(Date),month = format(Date,"%Y-%m")) %>%
  group_by(MerchantID,month) %>%
  mutate(HitsPerMonth = n_distinct(CardNum))

如果每个CardNum只需计算一次MerchantID,而与月份无关,则可以执行以下操作:

df %>%
  mutate(Date = as.Date(Date),"%Y-%m")) %>%
  group_by(MerchantID) %>%
  mutate(CardNum = replace(CardNum,duplicated(CardNum),NA)) %>%
  group_by(month,.add  =TRUE) %>%
  mutate(HitsPerMonth = n_distinct(na.omit(CardNum)))
,

您可以使用ave并计算唯一长度。

df <- transform(df,hits.pm=ave(CardNum,MerchantID,substr(Date,6,7),FUN=function(x) length(unique(x))))
df
#   MerchantID CardNum       Date hits.pm
# 1       1234   1abc1 2020-05-07       1
# 2       1234   1abc1 2020-05-07       1
# 3       1234   2xyz2 2019-10-12       2
# 4       1234   3ijk3 2019-10-25       2
# 5       1235   1abc1 2020-05-07       1
# 6       1236   1abc1 2020-05-07       1
# 7       1235   2xyz2 2019-10-12       2
# 8       1235   3ijk3 2019-10-25       2

数据:

df <- read.table(header=T,text="  MerchantID CardNum       Date
1       1234   1abc1 2020-05-07
2       1234   1abc1 2020-05-07
3       1234   2xyz2 2019-10-12
4       1234   3ijk3 2019-10-25
5       1235   43bc1 2020-05-07
6       1235   foo12 2020-05-07
7       1236   foo34 2019-10-12
8       1236   foo34 2019-10-25
                 ")