【发布时间】:2020-07-30 19:43:16
【问题描述】:
我有一个数据框列表,每个数据框都有多个列,其中包含我想删除并替换为 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
【问题讨论】:
-
当然该函数不起作用,因为计算平均值和标准差时会考虑极端值等情况。因此,价值将保持不变。您可以尝试删除大于
IQR(x)或quantile(x,0.75)的值,如果您想要这样的方法,请告诉我! -
您还会收到警告,因为您正试图从
data_time列中删除异常值。假设所有列都是数字,该函数被清楚地编写。当我在您的代码上运行您的数据时,我收到了 12 条警告!您的示例数据中只有 17 行,但pnorm(-3) * 2 = .0027因此,如果数据是正态分布的,那么在 1000 次观察中您只会期望 2.7 个异常值。