通过对异常值按组取中位数来纠正变量中的错误
Correcting errors in variables, by taking the median by group for outliers
示例数据:
library(data.table)
set.seed(1)
DT <- data.table(panelID = sample(10,10),
some_NA = sample(0:5, 6),
some_NA_factor = sample(0:5, 6),
Group = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)),
Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5),
wt = 15*round(runif(100)/10,2),
Income = round(rnorm(10,-5,5),2),
Happiness = sample(10,10),
Sex = round(rnorm(10,0.75,0.3),2),
Age = sample(100,100),
Height= 150*round(rnorm(10,0.75,0.3),2))
# ERRORS
DT [1:5,11] <- 0
我在 Height
注册数据时遇到了一些错误。由于数据是面板数据,我应该能够从其他观察结果中推断出实际的 Height
。为了使这个过程自动化,我考虑用中位数替换一个值,如果该值距离中位数超过 50 厘米:
setDT(DT)[abs(median(Height, na.rm = TRUE) - Height) > 50 , newheight := median(Height, na.rm = TRUE), by=panelID]
不知何故 by
参数不起作用,导致以下结果:
> table(DT$newheight)
0 27 165
4 10 10
谁能告诉我我做错了什么?
你的问题出在操作顺序上。首先,过滤器(即逗号前的位)正在应用于整个table,因此此处计算的中位数是整个高度列的中位数。然后,在每个组中应用逗号后的位, 到过滤后的数据。所以你实际上使用的是异常值 的中位数 ,而不是整个组的中位数(我假设这是你想要的)。
一个解决方法是分阶段进行:
setDT(DT)
DT[, median.height:= median(Height, na.rm = TRUE), by='panelID']
DT[abs(Height - median.height) > 50, newheight:= median.height]
或者,您可能打算将最后一行替换为:
DT[, newheight:= fifelse(abs(Height - median.height) > 50, median.height, Height)]
尝试:
setDT(DT)
DT[ , newheight := ifelse(abs(median(Height, na.rm = TRUE) - Height) > 50, median(Height, na.rm = TRUE), Height), by=.(panelID)]
示例数据:
library(data.table)
set.seed(1)
DT <- data.table(panelID = sample(10,10),
some_NA = sample(0:5, 6),
some_NA_factor = sample(0:5, 6),
Group = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)),
Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5),
wt = 15*round(runif(100)/10,2),
Income = round(rnorm(10,-5,5),2),
Happiness = sample(10,10),
Sex = round(rnorm(10,0.75,0.3),2),
Age = sample(100,100),
Height= 150*round(rnorm(10,0.75,0.3),2))
# ERRORS
DT [1:5,11] <- 0
我在 Height
注册数据时遇到了一些错误。由于数据是面板数据,我应该能够从其他观察结果中推断出实际的 Height
。为了使这个过程自动化,我考虑用中位数替换一个值,如果该值距离中位数超过 50 厘米:
setDT(DT)[abs(median(Height, na.rm = TRUE) - Height) > 50 , newheight := median(Height, na.rm = TRUE), by=panelID]
不知何故 by
参数不起作用,导致以下结果:
> table(DT$newheight)
0 27 165
4 10 10
谁能告诉我我做错了什么?
你的问题出在操作顺序上。首先,过滤器(即逗号前的位)正在应用于整个table,因此此处计算的中位数是整个高度列的中位数。然后,在每个组中应用逗号后的位, 到过滤后的数据。所以你实际上使用的是异常值 的中位数 ,而不是整个组的中位数(我假设这是你想要的)。
一个解决方法是分阶段进行:
setDT(DT)
DT[, median.height:= median(Height, na.rm = TRUE), by='panelID']
DT[abs(Height - median.height) > 50, newheight:= median.height]
或者,您可能打算将最后一行替换为:
DT[, newheight:= fifelse(abs(Height - median.height) > 50, median.height, Height)]
尝试:
setDT(DT)
DT[ , newheight := ifelse(abs(median(Height, na.rm = TRUE) - Height) > 50, median(Height, na.rm = TRUE), Height), by=.(panelID)]