您如何计算每种类型的平均评分

How do you calculate the average rating per genre

我有一个包含 30 列的文件。其中包括 userid、itemid、moviename、rating、date,其余用于对电影所属的流派进行分类。流派类别是行中带有二进制值的列名称。如果一部电影属于一个流派,它在相应的列下有一个 1,否则为 0。我想计算每个流派的平均评分,想知道是否有更短的流程可用?

我目前尝试通过选择值为“1”的每个流派来过滤数据,然后计算平均评分。但我有将近 24 种类型,我认为以这种方式进行是低效的。我尝试过的另一种方法是遍历流派列并再次过滤每个流派,其中值为“1”但循环消耗大量时间并且当数据设置很大(超过 100K 行)时,R 有时会播放为我注意到了。

我想问一下是否有另一种方法可以避免像 melt、dcast 这样的循环或其他可以完成相同工作的方法?

我正在提供我的数据集的 dput

dput(data)
structure(list(user_id = c(10L, 890L, 867L, 5L, 320L, 630L, 151L, 
699L, 21L, 450L, 179L, 135L, 314L, 487L, 735L, 823L, 169L, 889L, 
846L), item_id = c(447L, 660L, 191L, 441L, 1052L, 568L, 414L, 
1061L, 872L, 33L, 302L, 581L, 568L, 280L, 181L, 503L, 498L, 207L, 
497L), Movie_title = structure(c(6L, 11L, 2L, 3L, 9L, 17L, 15L, 
10L, 14L, 8L, 13L, 12L, 17L, 18L, 16L, 5L, 1L, 7L, 4L), .Label = c("African Queen, The (1951)", 
"Amadeus (1984)", "Amityville Horror, The (1979)", "Bringing Up Baby (1938)", 
"Candidate, The (1972)", "Carrie (1976)", "Cyrano de Bergerac (1990)", 
"Desperado (1995)", "Dracula: Dead and Loving It (1995)", "Evening Star, The (1996)", 
"Fried Green Tomatoes (1991)", "Kalifornia (1993)", "L.A. Confidential (1997)", 
"Love Jones (1997)", "My Favorite Year (1982)", "Return of the Jedi (1983)", 
"Speed (1994)", "Up Close and Personal (1996)"), class = "factor"), 
    Rating = c(4L, 2L, 5L, 1L, 2L, 4L, 5L, 3L, 2L, 5L, 4L, 4L, 
    5L, 5L, 4L, 5L, 3L, 3L, 5L), Date = structure(c(7L, 15L, 
    12L, 4L, 1L, 2L, 9L, 8L, 19L, 14L, 18L, 10L, 6L, 16L, 5L, 
    11L, 17L, 13L, 3L), .Label = c("1/14/1998", "1/25/1998", 
    "1/5/1998", "10/1/1997", "10/13/1997", "10/26/1997", "10/27/1997", 
    "11/10/1997", "11/15/1997", "11/18/1997", "11/2/1997", "11/21/1997", 
    "11/22/1997", "12/18/1997", "12/24/1997", "12/30/1997", "3/31/1998", 
    "4/10/1998", "9/22/1997"), class = "factor"), unknown = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Action = c(0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 
    1L, 0L, 0L, 1L, 0L, 1L, 0L, 1L, 1L, 0L), Adventure = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 
    1L, 0L, 0L), Animation = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Children = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Comedy = c(0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), Crime = c(0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L), Documentary = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Drama = c(0L, 
    1L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 1L, 
    0L, 1L, 0L), Fantasy = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Film.Noir = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Horror = c(1L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Musical = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Mystery = c(0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Romance = c(0L, 
    0L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 
    1L, 1L, 0L), Sci.Fi = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L), Thriller = c(0L, 
    0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 
    0L, 0L, 0L), War = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L), Western = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Short = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), History = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Biography = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Sport = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), Family = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("user_id", 
"item_id", "Movie_title", "Rating", "Date", "unknown", "Action", 
"Adventure", "Animation", "Children", "Comedy", "Crime", "Documentary", 
"Drama", "Fantasy", "Film.Noir", "Horror", "Musical", "Mystery", 
"Romance", "Sci.Fi", "Thriller", "War", "Western", "Short", "History", 
"Biography", "Sport", "Family"), class = "data.frame", row.names = c(NA, 
-19L))

这是 dplyr and tidyr 的一个很好的用例:

library(dplyr)
library(tidyr)
dat %>% gather(genre, value, unknown:Family) %>% filter(value == 1) %>%
    group_by(genre) %>% summarize(average = mean(Rating))

此代码:

  • 将 movie/genre 对中的每一对收集到一个单独的行中(每部电影会有多行)
  • 仅过滤电影属于某个流派的情况
  • 按流派分组,并在每个类别中进行汇总以找到平均评分(您也可以执行其他操作,例如中位数或标准差)

老办法也行:

genres <- c('Action','Adventure','Animation')
means <- numeric(length(genres))
names(means) <- genres
for(g in genres)
    meanRatings[g] <- mean(myData$Rating[mydata[,g]==1])
means