R - 跨列的不同计数

R - Distinct count across columns

我有一个庞大而复杂的数据集(有点太复杂了,不能在这里分享,而且可能没有必要分享整个数据集)但这里有一个它看起来像的例子。这只是一天,完整样本跨越数百天:

我想做的是设计一种方法来计算每个 RowGenre 的变化。更简单地说(我希望):每个 Row 有 12 个 Column,我想测量 Genre 在这 12 个 Column 中的变化(这是 BBC iPlayer,你们中的许多人可能都很熟悉)。例如。如果 Row 由 4 个“体育”、4 个“剧情”和 4 个“纪录片”组成,则将有 3 个流派的不同计数。

我认为简单的不同计数是衡量每一行内变化的好方法(计数越不同,变化越大),但这不是一种非常微妙的方法。 IE。如果一行由 11 个“运动”和 1 个“纪录片”组成,则不同的计数为 2。如果它由 6 个“运动”和 6 个“纪录片”组成,它仍然是不同的计数 2 - 所以不同的计数并不是真的在这个意义上帮助。

我想我在这里就两件事征求意见:

我希望一切都清楚,但如果没有,我很乐意详细说明任何事情。也许值得注意(正如我上面提到的)我想确定特定日期的变化,这里共享的示例数据只是一个日期(但我有数百个)。

提前致谢:)

*** 更新 ***

感谢您的评论 - 特别是关于分享真实数据的快照(您将在下面找到)。抱歉 - 我在这方面有点新手,不太熟悉正确的约定!

这是一个数据样本 - 我希望它是正确的,我希望它能有所帮助:

structure(list(Row = c(0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 
3L, 3L, 3L, 3L), Genre = c("", "Sport", "Drama", "Documentary", 
"Entertainment", "Drama", "Comedy", "Crime Drama", "Entertainment", 
"Documentary", "Entertainment", "History", "Crime Drama", "", 
"", "", "", "", "", "", "", "", "", "", "", "Drama", "Drama", 
"Documentary", "Entertainment", "Period Drama"), Column = c(1L, 
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 
4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L)), row.names = c(NA, 
30L), class = "data.frame")

首先创建一些可重现的数据。我们只需要 RowGenre:

set.seed(42)
Row <- rep(1:10, each=10)
Genre <- sample(c("Sport", "Drama", "Documentary", "Entertainment", "History", "Crime Drama", "Period Drama", "Film - Comedy", "Film-Thriller"), 100, replace=TRUE)
example <- data.frame(Row, Genre)
str(example)
# 'data.frame': 100 obs. of  2 variables:
#  $ Row  : int  1 1 1 1 1 1 1 1 1 1 ...
#  $ Genre: chr  "Sport" "History" "Sport" "Film-Thriller" ...

现在获取每一行中不同流派的数量:

Count <- tapply(example$Genre, example$Row, function(x) length(unique(x)))
Count
#  1  2  3  4  5  6  7  8  9 10 
#  7  5  6  7  6  8  7  7  7  6 

第 1 行有 7 个类型,第 2 行只有 5 个类型。更多详情:

xtabs(~Genre+Row, example)
#                 Row
#  Genre           1 2 3 4 5 6 7 8 9 10
#    Crime Drama   0 0 1 1 3 1 1 0 2  1
#    Documentary   0 1 1 1 1 0 1 0 1  0
#    Drama         1 1 1 3 2 1 2 1 1  0
#    Entertainment 2 2 3 1 1 1 1 2 0  0
#    Film - Comedy 1 0 3 2 0 1 2 2 0  2
#    Film-Thriller 1 3 0 0 0 1 1 1 2  2
#    History       1 3 0 1 2 1 2 2 2  1
#    Period Drama  1 0 0 1 0 2 0 1 1  2
#    Sport         3 0 1 0 1 2 0 1 1  2

可重现的样本数据:

set.seed(42)
sampdata <- transform(
  expand.grid(Date = Sys.Date() + 0:2, Row=0:3, Column=1:12), 
  Genre = sample(c("Crime Drama","Documentary","Drama","Entertainment"), 
                 size = 48, replace = TRUE)
)
head(sampdata)
#         Date Row Column         Genre
# 1 2022-02-18   0      1   Crime Drama
# 2 2022-02-19   0      1   Crime Drama
# 3 2022-02-20   0      1   Crime Drama
# 4 2022-02-18   1      1   Crime Drama
# 5 2022-02-19   1      1   Documentary
# 6 2022-02-20   1      1 Entertainment
nrow(sampdata)
# [1] 144

使用dplyrtidyr,我们可以分组,汇总,然后进行透视:

library(dplyr)
# library(tidyr) # pivot_wider
sampdata %>%
  group_by(Date, Row) %>%
  summarize(
    Uniq = n_distinct(Genre),
    Var = var(table(Genre))
  ) %>%
  tidyr::pivot_wider(
    Date, names_from = Row, values_from = c(Uniq, Var)
  ) %>%
  ungroup()
# # A tibble: 3 x 9
#   Date       Uniq_0 Uniq_1 Uniq_2 Uniq_3 Var_0 Var_1 Var_2 Var_3
#   <date>      <int>  <int>  <int>  <int> <dbl> <dbl> <dbl> <dbl>
# 1 2022-02-18      2      3      2      2     0     3    18    18
# 2 2022-02-19      3      3      1      3     3     3    NA     3
# 3 2022-02-20      2      3      3      3    18     3     3     3

两件事:Uniq_# 是每个 Row 不同 Genre 值的计数,Var_# 方差 的计数。例如,在您的示例中,计数为 6 和 6 的两个类型的方差为 0,但计数为 11 和 1 的方差为 50 (var(c(11,1))),表明该类型的变化更大Date/Row组合。

因为我们用的是group_by,如果你的分组变量再多一些,那就是straight-forward来扩展这个,无论是在分组上还是在聚合上除了[=24我们还能做什么=] 和 var(.).

顺便说一句:根据您的其他计算、分析和 reporting/plotting,将其保留为 long 格式可能会有用,删除 pivot_wider.

sampdata %>%
  group_by(Date, Row) %>%
  summarize(
    Uniq = n_distinct(Genre),
    Var = var(table(Genre))
  ) %>%
  ungroup()
# # A tibble: 12 x 4
#    Date         Row  Uniq   Var
#    <date>     <int> <int> <dbl>
#  1 2022-02-18     0     2     0
#  2 2022-02-18     1     3     3
#  3 2022-02-18     2     2    18
#  4 2022-02-18     3     2    18
#  5 2022-02-19     0     3     3
#  6 2022-02-19     1     3     3
#  7 2022-02-19     2     1    NA
#  8 2022-02-19     3     3     3
#  9 2022-02-20     0     2    18
# 10 2022-02-20     1     3     3
# 11 2022-02-20     2     3     3
# 12 2022-02-20     3     3     3

何时保持它的好例子包括 Date/Row 的进一步聚合和 ggplot2 的绘图(这确实奖励 long-data)。