我有一个数据框列表,每个数据框都有多个列,其中包含我想删除并替换为NA的异常值。我的数据集非常大(每个数据框有11列,每行约有15,000行),因此我尽力在下面创建一个可重现的示例:
df1 <- data.frame(date_time = c("2019-01-01", "2019-01-02", "2019-01-03", "2019-01-04", "2019-01-05", "2019-01-06", "2019-01-07", "2019-01-08", "2019-01-09", "2019-01-10", "2019-01-11", "2019-01-12", "2019-01-13", "2019-01-14", "2019-01-15","2019-01-16","2019-01-17"),
XH_warmed_air_1m = c(25, 23, 26, 30, 10, 15, 12, 0, 1, 5, -15, -12, -6, -1, 537, 435, 300),
XH_ambient_air_1m = c(25, 23, 26, 30, 10, 15, 12, 0, 1, 5, -15, -12, -6, -1, 537, 435, 300))
df2 <- data.frame(date_time = c("2019-01-01", "2019-01-02", "2019-01-03", "2019-01-04", "2019-01-05", "2019-01-06", "2019-01-07", "2019-01-08", "2019-01-09", "2019-01-10", "2019-01-11", "2019-01-12", "2019-01-13", "2019-01-14", "2019-01-15","2019-01-16","2019-01-17"),
XH_warmed_air_1m = c(25, 23, 26, 30, 10, 15, 12, 0, 1, 5, -15, -12, -6, -1, 537, 435, 300),
XH_ambient_air_1m = c(25, 23, 26, 30, 10, 15, 12, 0, 1, 5, -15, -12, -6, -1, 537, 435, 300))
df3 <- data.frame(date_time = c("2019-01-01", "2019-01-02", "2019-01-03", "2019-01-04", "2019-01-05", "2019-01-06", "2019-01-07", "2019-01-08", "2019-01-09", "2019-01-10", "2019-01-11", "2019-01-12", "2019-01-13", "2019-01-14", "2019-01-15","2019-01-16","2019-01-17"),
XH_warmed_air_1m = c(25, 23, 26, 30, 10, 15, 12, 0, 1, 5, -15, -12, -6, -1, 537, 435, 300),
XH_ambient_air_1m = c(25, 23, 26, 30, 10, 15, 12, 0, 1, 5, -15, -12, -6, -1, 537, 435, 300))
list_df <- list(df1=df1, df2=df2, df3=df3)
我想做一个函数,用NA替换每列离均值3 sd的离群值。在给定的示例中,离群值是537、435和300,但是我的实际数据具有一定范围的离群值。以下是我发现的here函数,我试图将其用于此目的。
remove_outliers <- function(df){
columns <- colnames(df)
for (i in columns){
Min <- mean(df[[i]]) - (3*sd(df[[i]]))
Max <- mean(df[[i]]) + (3*sd(df[[i]]))
df[[i]][df[[i]] < Min | df[[i]] > Max] <- NA
}
return(df)
}
list_df <- lapply(list_df, remove_outliers)
当我尝试将函数应用于列表时,它似乎没有任何作用。如何解决此功能,以便删除列表中每个数据框中的所有列(date_time列除外)?
使用R版本3.5.1,Mac OS X 10.13.6
答案 0 :(得分:1)
我认为@Duck的评论在这里非常有用。使用整个数据集计算均值和标准差时,您将计算的离群值包括在内。这不会删除示例中的三个异常值。在计算均值和标准差之前,应先以某种方式限制数据,然后根据这些计算,可以消除异常值。也就是说,您应该从范围的高端/低端删除一些案例。问题是,在计算均值和标准差之前,您将排除多少个案例(或占案例的比例)?在这里,您可以使用 quantile 函数。这是我修改您的函数的方式:
remove_outliers = function(df) {
for (i in 2:ncol(df)) {
dat = df[which(df[,i] > quantile(df[,i], .1) & df[,i] < quantile(df[,i], .9)),i]
mean = mean(dat)
sd = sd(dat)
df[which( abs((df[,i]) - mean) > (sd * 3)), i] = NA
}
return(df)
}
这是将函数应用于df1的结果:
> remove_outliers(df1)
date_time XH_warmed_air_1m XH_ambient_air_1m
1 2019-01-01 25 25
2 2019-01-02 23 23
3 2019-01-03 26 26
4 2019-01-04 30 30
5 2019-01-05 10 10
6 2019-01-06 15 15
7 2019-01-07 12 12
8 2019-01-08 0 0
9 2019-01-09 1 1
10 2019-01-10 5 5
11 2019-01-11 -15 -15
12 2019-01-12 -12 -12
13 2019-01-13 -6 -6
14 2019-01-14 -1 -1
15 2019-01-15 NA NA
16 2019-01-16 NA NA
17 2019-01-17 NA NA
此外,正如@dcarlson所说,您正在将该函数应用于date_time列。我从函数中排除了该列。