如何处理 R 中面板数据中观察值内和观察值之间的异常值?
How to deal with outliers within and between observations in a panel data in R?
我有一个数据集显示了大约 100.000 家公司 20 年来的收入。数据有许多其他变量,但是,下面,我正在编写该数据集的简化样本的可重现版本。
my_data <- data.frame(Company = c("A","B","C","D"), CITY = c("Paris", "Paris", "Quimper", "Nice"), year_creation = c("2010", "2009", "2008", "2009"), revenue_2008 = c(NA, NA, 10, NA),
revenue_2009 = c(NA,10, 20, 15000), revenue_2010 = c(02, 10, 2500, 20000), revenue_2011 = c(14, 16, 10, 30000),
size = c(2, 3, 5, 1))
如您所见,我正在处理一个不平衡的面板数据,该数据在观察值内(例如,公司 C 在 2010 年的突然收入)和观察值之间(例如,公司D 的收入比其他公司高得多,即使考虑到我选择了应该相似的公司)...
那么,我的问题是,在 R 中处理这两类异常值的最佳方法是什么?我想对于within outliers,wide-format的数据应该会好一些吧?但是哪个代码可以 运行 逐行检查异常值(即逐个观察)?
对于第二种类型的异常值?将数据转换为长格式更好吗?如果是,我如何测试长格式的异常值?
非常感谢您的帮助!
最好的,
如何检测主要是统计问题。您可以使用的一种方法是 Hampel 过滤器(其优缺点不在本答案的范围内)。
它将 median ± 3*(median absolute deviation)
之外的值视为异常值。
假设我们将使用这个标准。您可以通过 data.table
.
的 by
参数在测试内部和测试之间进行
Is it better to convert the data for the long format?
这会让分析更容易,因此我通过melt
转换了它
my_data <- data.frame(Company = c("A","B","C","D"), CITY = c("Paris", "Paris", "Quimper", "Nice"), year_creation = c("2010", "2009", "2008", "2009"), revenue_2008 = c(NA, NA, 10, NA),
revenue_2009 = c(NA,10, 20, 15000), revenue_2010 = c(02, 10, 2500, 20000), revenue_2011 = c(14, 16, 10, 30000),
size = c(2, 3, 5, 1))
library(data.table)
my_data <- as.data.table(my_data)
my_data <- melt(my_data, id.vars = c("Company", "CITY", "year_creation", "size"))
hampel_filter <- function(x){
x_med <- median(x, na.rm = TRUE)
x_mad <- mad(x, na.rm = TRUE)
(x > x_med + 3*x_mad | x < x_med - 3*x_mad)
}
my_data[, between_out := hampel_filter(value), by = variable]
my_data[, within_out := hampel_filter(value), by = Company]
> my_data
Company CITY year_creation size variable value between_out within_out
1: A Paris 2010 2 revenue_2008 NA NA NA
2: B Paris 2009 3 revenue_2008 NA NA NA
3: C Quimper 2008 5 revenue_2008 10 FALSE FALSE
4: D Nice 2009 1 revenue_2008 NA NA NA
5: A Paris 2010 2 revenue_2009 NA NA NA
6: B Paris 2009 3 revenue_2009 10 FALSE FALSE
7: C Quimper 2008 5 revenue_2009 20 FALSE FALSE
8: D Nice 2009 1 revenue_2009 15000 TRUE FALSE
9: A Paris 2010 2 revenue_2010 2 FALSE FALSE
10: B Paris 2009 3 revenue_2010 10 FALSE FALSE
11: C Quimper 2008 5 revenue_2010 2500 FALSE TRUE
12: D Nice 2009 1 revenue_2010 20000 TRUE FALSE
13: A Paris 2010 2 revenue_2011 14 FALSE FALSE
14: B Paris 2009 3 revenue_2011 16 FALSE TRUE
15: C Quimper 2008 5 revenue_2011 10 FALSE FALSE
16: D Nice 2009 1 revenue_2011 30000 TRUE FALSE
您还可以使用 DescTools
中的 Winsorize()
同时检测和处理异常值。查看详情:https://en.wikipedia.org/wiki/Winsorizing
我有一个数据集显示了大约 100.000 家公司 20 年来的收入。数据有许多其他变量,但是,下面,我正在编写该数据集的简化样本的可重现版本。
my_data <- data.frame(Company = c("A","B","C","D"), CITY = c("Paris", "Paris", "Quimper", "Nice"), year_creation = c("2010", "2009", "2008", "2009"), revenue_2008 = c(NA, NA, 10, NA),
revenue_2009 = c(NA,10, 20, 15000), revenue_2010 = c(02, 10, 2500, 20000), revenue_2011 = c(14, 16, 10, 30000),
size = c(2, 3, 5, 1))
如您所见,我正在处理一个不平衡的面板数据,该数据在观察值内(例如,公司 C 在 2010 年的突然收入)和观察值之间(例如,公司D 的收入比其他公司高得多,即使考虑到我选择了应该相似的公司)...
那么,我的问题是,在 R 中处理这两类异常值的最佳方法是什么?我想对于within outliers,wide-format的数据应该会好一些吧?但是哪个代码可以 运行 逐行检查异常值(即逐个观察)? 对于第二种类型的异常值?将数据转换为长格式更好吗?如果是,我如何测试长格式的异常值?
非常感谢您的帮助! 最好的,
如何检测主要是统计问题。您可以使用的一种方法是 Hampel 过滤器(其优缺点不在本答案的范围内)。
它将 median ± 3*(median absolute deviation)
之外的值视为异常值。
假设我们将使用这个标准。您可以通过 data.table
.
by
参数在测试内部和测试之间进行
Is it better to convert the data for the long format?
这会让分析更容易,因此我通过melt
my_data <- data.frame(Company = c("A","B","C","D"), CITY = c("Paris", "Paris", "Quimper", "Nice"), year_creation = c("2010", "2009", "2008", "2009"), revenue_2008 = c(NA, NA, 10, NA),
revenue_2009 = c(NA,10, 20, 15000), revenue_2010 = c(02, 10, 2500, 20000), revenue_2011 = c(14, 16, 10, 30000),
size = c(2, 3, 5, 1))
library(data.table)
my_data <- as.data.table(my_data)
my_data <- melt(my_data, id.vars = c("Company", "CITY", "year_creation", "size"))
hampel_filter <- function(x){
x_med <- median(x, na.rm = TRUE)
x_mad <- mad(x, na.rm = TRUE)
(x > x_med + 3*x_mad | x < x_med - 3*x_mad)
}
my_data[, between_out := hampel_filter(value), by = variable]
my_data[, within_out := hampel_filter(value), by = Company]
> my_data
Company CITY year_creation size variable value between_out within_out
1: A Paris 2010 2 revenue_2008 NA NA NA
2: B Paris 2009 3 revenue_2008 NA NA NA
3: C Quimper 2008 5 revenue_2008 10 FALSE FALSE
4: D Nice 2009 1 revenue_2008 NA NA NA
5: A Paris 2010 2 revenue_2009 NA NA NA
6: B Paris 2009 3 revenue_2009 10 FALSE FALSE
7: C Quimper 2008 5 revenue_2009 20 FALSE FALSE
8: D Nice 2009 1 revenue_2009 15000 TRUE FALSE
9: A Paris 2010 2 revenue_2010 2 FALSE FALSE
10: B Paris 2009 3 revenue_2010 10 FALSE FALSE
11: C Quimper 2008 5 revenue_2010 2500 FALSE TRUE
12: D Nice 2009 1 revenue_2010 20000 TRUE FALSE
13: A Paris 2010 2 revenue_2011 14 FALSE FALSE
14: B Paris 2009 3 revenue_2011 16 FALSE TRUE
15: C Quimper 2008 5 revenue_2011 10 FALSE FALSE
16: D Nice 2009 1 revenue_2011 30000 TRUE FALSE
您还可以使用 DescTools
中的 Winsorize()
同时检测和处理异常值。查看详情:https://en.wikipedia.org/wiki/Winsorizing