使用多列创建数据透视表 table 并按唯一出现次数进行聚合

Making Pivot table with Multiple Columns and Aggregating by Unique Occurences

我很难思考这个问题或在网上找到指南。

我有会员数据。我想看看有多少会员在取消会员资格之前在特定月份坚持了下来。我可以看到他们加入的月份,我可以通过查看他们的交易号(每月增加 1)来了解他们活跃了多长时间。因此,如果我跟踪每个月的交易编号,我可以得到当月有多少人加入以及下降情况的瀑布图。

奇怪的是,有时同一会员在一个月内有多次交易,但我只想计算该会员一次,所以我只需要计算该会员一次。

Name | Joined Month | Transaction no
Adam | Jan          | 1
Adam | Jan          | 2
Adam | Jan          | 2
Ben  | Jan          | 1
Ben  | Jan          | 2
Ben  | Jan          | 3
Ben  | Jan          | 4
Cathy| Jan          | 1
Donna| Feb          | 1
Donna| Feb          | 2
Donna| Feb          | 3
Evan | Mar          | 1
Evan | Mar          | 1
Frank | Mar         | 1
Frank | Mar         | 2

对以月份为列的不同成员进行聚合,结果将如下所示:

Transaction# | Jan | Feb | March
1            | 3   | 1   | 2 
2            | 2   | 1   | 1
3            | 1   | 1   | 0
4            | 1   | 0   | 0

任何正确方向的提示或指示都会非常有帮助。我应该使用 reshape2 或类似的包吗?希望我没有破坏解释或格式,请随时提出任何问题。

谢谢!

下面是一个使用 tidyverse 函数 dplyr::n_distincttidyr::spread 的可重现示例。

我首先将您的数据表示为小标题(或者您也可以同样使用数据框)。

接下来我们按 TransactionnoJoinedMonth 分组,然后再计算不同的名称。要以 table 格式获取它,您要求我们使用 tidyr::spread。如果您希望按月顺序生成结果列,确保您的数据框将它们作为有序因素很重要。

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tibble)
library(tidyr)

x <- tribble(
        ~Name , ~JoinedMonth,  ~Transactionno,
        "Adam" , "Jan"         , 1,
        "Adam" , "Jan"          , 2,
        "Adam" , "Jan"          , 2,
        "Ben"  , "Jan"          , 1,
        "Ben"  , "Jan"          , 2,
        "Ben"  , "Jan"          , 3,
        "Ben"  , "Jan"          , 4,
        "Cathy", "Jan"          , 1,
        "Donna", "Feb"          , 1,
        "Donna", "Feb"          , 2,
        "Donna", "Feb"          , 3,
        "Evan" , "Mar"          , 1,
        "Evan" , "Mar"          , 1,
        "Frank" , "Mar"         , 1,
        "Frank" , "Mar"         , 2  

)

x %>%
  group_by(Transactionno, JoinedMonth) %>% 
  summarise(ct = n_distinct(Name)) %>% 
  tidyr::spread(JoinedMonth, ct, fill = 0)
#> # A tibble: 4 x 4
#> # Groups:   Transactionno [4]
#>   Transactionno   Feb   Jan   Mar
#>           <dbl> <dbl> <dbl> <dbl>
#> 1            1.    1.    3.    2.
#> 2            2.    1.    2.    1.
#> 3            3.    1.    1.    0.
#> 4            4.    0.    1.    0.

1) xtabs 这个单行代码使用基数 R 和输入 DF 可重复显示在下面的注释中。请注意,我们假设 Joined.Month 是具有 Jan、Feb、Mar 级别的因子,以确保输出按该顺序(而不是按字母顺序)排序。

xtabs(~ Transaction.no + Joined.Month, unique(DF))

给予:

              Joined.Month
Transaction.no Jan Feb Mar
             1   1   3   2
             2   1   2   1
             3   1   1   0
             4   0   1   0

2) table 另一种基础 R 方法。

with(unique(DF), table(Transaction.no, Joined.Month))

给予:

              Joined.Month
Transaction.no Jan Feb Mar
             1   3   1   2
             2   2   1   1
             3   1   1   0
             4   1   0   0

2a) 这也可以,而且更短但不是很清楚:

table(unique(DF)[3:2])

3) tapply 这也只使用基础 R:

u <- unique(DF)
tapply(u[[1]], u[3:2], length, default = 0)

给予:

              Joined.Month
Transaction.no Jan Feb Mar
             1   3   1   2
             2   2   1   1
             3   1   1   0
             4   1   0   0

备注

DF 以可重现的形式假定为:

Lines <- "Name | Joined Month | Transaction no
Adam | Jan          | 1
Adam | Jan          | 2
Adam | Jan          | 2
Ben  | Jan          | 1
Ben  | Jan          | 2
Ben  | Jan          | 3
Ben  | Jan          | 4
Cathy| Jan          | 1
Donna| Feb          | 1
Donna| Feb          | 2
Donna| Feb          | 3
Evan | Mar          | 1
Evan | Mar          | 1
Frank | Mar         | 1
Frank | Mar         | 2"

DF <- read.table(text = Lines, header = TRUE, sep = "|", 
  strip.white = TRUE, as.is = TRUE)
DF$Joined.Month <- factor(DF$Joined.Month, lev = month.abb[1:3])