假设我有:
Person Movie Rating
Sally Titanic 4
Bill Titanic 4
Rob Titanic 4
Sue Cars 8
Alex Cars **9**
Bob Cars 8
如您所见,亚历克斯存在矛盾。所有相同的电影都应该具有相同的排名,但亚历克斯有一个数据错误条目。如何使用 R 来解决此问题?我已经考虑了一段时间,但我无法弄清楚。我是否必须在 excel 或其他东西中手动执行此操作?R上是否有命令将返回两列之间存在数据矛盾的所有情况?
也许我可以让 R 做一个布尔检查,如果所有电影案例都与其第一次迭代的第一个评级匹配?对于所有返回"否"的内容,我可以手动查看吗?我将如何编写此函数?
谢谢
data.table
的解决方案
定义函数
Myfunc <- function(x) {
temp <- table(x)
names(temp)[which.max(temp)]
}
library(data.table)
创建具有正确评级的列(通过引用)
setDT(df)[, CorrectRating := Myfunc(Rating), Movie][]
# Person Movie Rating CorrectRating
# 1: Sally Titanic 4 4
# 2: Bill Titanic 4 4
# 3: Rob Titanic 4 4
# 4: Sue Cars 8 8
# 5: Alex Cars 9 8
# 6: Bob Cars 8 8
或者如果您想删除"差"评级
df[Rating == CorrectRating][]
# Person Movie Rating CorrectRating
# 1: Sally Titanic 4 4
# 2: Bill Titanic 4 4
# 3: Rob Titanic 4 4
# 4: Sue Cars 8 8
# 5: Bob Cars 8 8
看起来,在"电影"定义的每个组中,您正在寻找与最常见值不同的任何评级实例。
您可以使用 dplyr(擅长"按一列分组,然后在每个组中执行操作")以及此答案中定义的"Mode"函数来解决此问题,该函数可在向量中找到最常见的项目:
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
library(dplyr)
dat %>% group_by(Movie) %>% filter(Rating != Mode(Rating))
这将查找行与组的其余部分不一致的所有情况。如果您想删除它们,可以执行以下操作:
newdat <- dat %>% group_by(Movie) %>% filter(Rating == Mode(Rating))
如果要修复它们,请执行
newdat <- dat %>% group_by(Movie) %>% mutate(Rating = Mode(Rating))
您可以使用可重现的数据版本测试上述内容:
dat <- data.frame(Person = c("Sally", "Bill", "Rob", "Sue", "Alex", "Bob"),
Movie = rep(c("Titanic", "Cars"), each = 3),
Rating = c(4, 4, 4, 8, 9, 8))
如果目标是查看组中的所有值是否相同(或者是否存在一些差异),那么这可以是tapply
(或aggregate
等)的简单应用程序,与 var 等函数一起使用(或计算范围)。 如果所有值都相同,则方差和范围将为 0。 如果它是任何其他值(舍入误差之外),则必须有一个不同的值。 which
功能可以帮助识别群体/个人。
tapply(dat$Rating, dat$Movie, FUN=var)
which(.Last.value > 0.00001)
tapply(dat$Rating, dat$Movie, FUN=function(x)diff(range(x)))
which(.Last.value != 0)
which( abs(dat$Rating - ave(dat$Rating, dat$Movie)) > 0)
which.max( abs(dat$Rating - ave(dat$Rating, dat$Movie)) )
dat[.Last.value,]
为 mode 添加一个变量,这样我就可以查看数据是否有任何奇怪的情况,例如丢失数据、文本、许多不同的答案而不是罕见的异常等。我使用"x"作为您的数据集
# one of many functions to find mode, could use any other
modefunc <- function(x){
names(table(x))[table(x)==max(table(x))]
}
# add variable for mode split by Movie
x$mode <- ave(x = x$Rating,x$Movie,FUN = modefunc)
# do whatever you want with the records that are different
x[x$Rating != x$mode, ]
如果您想要另一个模式函数,请尝试其他模式函数