【问题标题】:How do you calculate the average rating per genre你如何计算每个流派的平均收视率
【发布时间】:2015-01-15 18:33:48
【问题描述】:

我有一个包含 30 列的文件。这些包括用户 ID、项目 ID、电影名称、评级、日期,其余用于对电影所属的类型进行分类。流派类别是在行中具有二进制值的列名。如果一部电影属于一种类型,则在相应列下为 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))

【问题讨论】:

  • 你能发布dput(yourdata)的结果吗?由于选项卡,很难从这种格式将其读入 R。
  • 由于我不熟悉 dput 的机制,所以我从原始数据中提取了前 10 行。
  • 你可以简单地做dput(head(yourdata, 10))。这会让某人将其粘贴到他们的 R 控制台中并获得相同的对象。实际上,您的文件需要大量的操作才能读入 R(因为没有保留标签)
  • 请忽略之前的cmets。 'dput' 的结果是字符太多。您能否推荐任何其他可以帮助您访问该示例数据的方法?
  • dput(head(yourdata, 3)) 怎么样?

标签: r preprocessor


【解决方案1】:

这是dplyrtidyr 的一个很好的用例:

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

这段代码:

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

【讨论】:

  • @user42571。别客气。另请注意,一旦您拥有tidied <- dat %>% gather(genre, value, unknown:Family) %>% filter(value == 1) 格式的文件,您就可以制作很酷的图。例如,试试library(ggplot2); ggplot(tidied, aes(genre, Rating)) + geom_boxplot()
  • 我想问一下 'tidyr' 包不适用于 3.0.3 版。我需要以前的版本才能使用它。我正在运行 RStudio-版本 0.98.1091
  • @user42571 您需要 R 3.1.0 或更高版本。 (绝对值得升级)
【解决方案2】:

老式的方法也可以:

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

【讨论】:

  • 我觉得不应该建议在 R 中为此类任务运行循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 2019-05-03
相关资源
最近更新 更多