从数据框列表中按条件删除异常值
Remove outliers by condition from list of data frames
我尝试创建一个函数,通过 cooks 距离从数据框列表中删除多个异常值。
目前有一些问题:
我可以将第 1 部分公式化为函数吗? 我尝试了几个没有解决的问题。我想为 lm 使用几个不同的变量 - 所以如果我可以使用 colnumbers 和数据帧的正则表达式语法作为输入参数,那就太好了。
第 2 部分 - 图的文件名不正确。它将列表中每个数据框中的第一个观察值作为文件名。我该如何纠正?
第 3 部分: 不创建没有异常值的数据框。打印消息后函数结束。我找不到我的错误。
data(iris)
iris.lst <- split(iris[, 1:2], iris$Species)
new_names <- c(paste0(unlist(levels(iris$Species)),"_data"))
for (i in 1:length(iris.lst)) {
assign(new_names[i], iris.lst[[i]])
}
# Part 1: Then cooks distances
fit <- lapply(mget(ls(pattern = "_data")),
function(x) lm(x[,1] ~ x[,3], data = x))
cooksd <-lapply(fit,cooks.distance)
# Part 2: Plot each data frame with suspected outlier
plots <- function(x){
jpeg(file=paste0(names(x),".jpeg")) # file names are numbers
#par(mfrow=c(2,1))
plot(x, pch="*", cex=2, main="Influential cases by Cooks distance") # plot cook's distance
abline(h = 3*mean(x, na.rm=T), col="red") # add cutoff line
text(x=1:length(x)+1, y=x, labels=ifelse(x > 3*mean(x, na.rm=T),
names(x),""), col="red")
dev.off()
}
myplots <- lapply(cooksd, plots)
# Part 3: give me new data frames without influential cases
show_influential_cases <- function(x){
# invisible(cooksd[["n_OG"]] <- lapply(cooksd, length)
influential <- lapply(x,function(x) names(x)[x > 3*mean(x, na.rm=T)])
test <- as.data.frame(unlist(influential))[,1]
test <- as.numeric(test)
}
tested <- show_influential_cases(result)
cleaned_data <- add_new[-tested,] # removing outliers by indexing
有人可以帮我改进我的代码吗?
非常感谢,
纳丁
一般来说,在全局环境中创建多个数据框不是一个好习惯。列表总是更好的选择,它们易于管理。
第 1 部分 -
您可以将多个步骤合并到一个 lapply
函数中。在第 1 部分中,我们在同一个 lapply
调用中一起应用 lm
和 cooks.distance
函数。
master_data <- split(iris[, 1:2], iris$Species)
data <- lapply(master_data, function(x) {
cooks.distance(lm(Sepal.Length ~ Sepal.Width, data = x))
})
new_names <- paste0(levels(iris$Species),"_data")
names(data) <- new_names
第 2 部分 -
lapply
无法访问列表的名称,单独传递它们并使用 Map
调用 plots
函数。
plots <- function(x, y){
jpeg(file=paste0(y,".jpeg"))
plot(x, pch="*", cex=2, main="Influential cases by Cooks distance")
abline(h = 3*mean(x, na.rm=T), col="red") # add cutoff line
text(x=1:length(x)+1,y=x,labels=ifelse(x > 3*mean(x, na.rm=T),y,""), col="red")
dev.off()
}
Map(plots, data, names(data))
第 3 部分 -
我不太清楚你想如何执行第 3 部分,但现在我分别显示离群值和数据。
remove_influential_cases <- function(x, y){
inds <- x > 3*mean(x, na.rm=TRUE)
y[!inds, ]
}
result <- Map(remove_influential_cases, data, master_data)
我尝试创建一个函数,通过 cooks 距离从数据框列表中删除多个异常值。 目前有一些问题:
我可以将第 1 部分公式化为函数吗? 我尝试了几个没有解决的问题。我想为 lm 使用几个不同的变量 - 所以如果我可以使用 colnumbers 和数据帧的正则表达式语法作为输入参数,那就太好了。
第 2 部分 - 图的文件名不正确。它将列表中每个数据框中的第一个观察值作为文件名。我该如何纠正?
第 3 部分: 不创建没有异常值的数据框。打印消息后函数结束。我找不到我的错误。
data(iris)
iris.lst <- split(iris[, 1:2], iris$Species)
new_names <- c(paste0(unlist(levels(iris$Species)),"_data"))
for (i in 1:length(iris.lst)) {
assign(new_names[i], iris.lst[[i]])
}
# Part 1: Then cooks distances
fit <- lapply(mget(ls(pattern = "_data")),
function(x) lm(x[,1] ~ x[,3], data = x))
cooksd <-lapply(fit,cooks.distance)
# Part 2: Plot each data frame with suspected outlier
plots <- function(x){
jpeg(file=paste0(names(x),".jpeg")) # file names are numbers
#par(mfrow=c(2,1))
plot(x, pch="*", cex=2, main="Influential cases by Cooks distance") # plot cook's distance
abline(h = 3*mean(x, na.rm=T), col="red") # add cutoff line
text(x=1:length(x)+1, y=x, labels=ifelse(x > 3*mean(x, na.rm=T),
names(x),""), col="red")
dev.off()
}
myplots <- lapply(cooksd, plots)
# Part 3: give me new data frames without influential cases
show_influential_cases <- function(x){
# invisible(cooksd[["n_OG"]] <- lapply(cooksd, length)
influential <- lapply(x,function(x) names(x)[x > 3*mean(x, na.rm=T)])
test <- as.data.frame(unlist(influential))[,1]
test <- as.numeric(test)
}
tested <- show_influential_cases(result)
cleaned_data <- add_new[-tested,] # removing outliers by indexing
有人可以帮我改进我的代码吗? 非常感谢, 纳丁
一般来说,在全局环境中创建多个数据框不是一个好习惯。列表总是更好的选择,它们易于管理。
第 1 部分 -
您可以将多个步骤合并到一个 lapply
函数中。在第 1 部分中,我们在同一个 lapply
调用中一起应用 lm
和 cooks.distance
函数。
master_data <- split(iris[, 1:2], iris$Species)
data <- lapply(master_data, function(x) {
cooks.distance(lm(Sepal.Length ~ Sepal.Width, data = x))
})
new_names <- paste0(levels(iris$Species),"_data")
names(data) <- new_names
第 2 部分 -
lapply
无法访问列表的名称,单独传递它们并使用 Map
调用 plots
函数。
plots <- function(x, y){
jpeg(file=paste0(y,".jpeg"))
plot(x, pch="*", cex=2, main="Influential cases by Cooks distance")
abline(h = 3*mean(x, na.rm=T), col="red") # add cutoff line
text(x=1:length(x)+1,y=x,labels=ifelse(x > 3*mean(x, na.rm=T),y,""), col="red")
dev.off()
}
Map(plots, data, names(data))
第 3 部分 -
我不太清楚你想如何执行第 3 部分,但现在我分别显示离群值和数据。
remove_influential_cases <- function(x, y){
inds <- x > 3*mean(x, na.rm=TRUE)
y[!inds, ]
}
result <- Map(remove_influential_cases, data, master_data)