通过将异常值按组取中值来纠正变量中的错误

问题描述

示例数据:

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,Group = c(rep(1,20),rep(2,rep(3,rep(4,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,Happiness = sample(10,Sex = round(rnorm(10,0.75,0.3),Age = sample(100,100),Height= 150*round(rnorm(10,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 

有人可以告诉我我在做什么错吗?

解决方法

您的问题按操作顺序排列。首先,将过滤器(即逗号前的位)应用于整个表格,因此此处计算的中位数是整个“高度”列的中位数。然后,在每个组中将逗号后的位应用于过滤后的数据。因此,您实际上使用的是异常值的中位数 ,而不是整个组的中位数(我认为这是您的预期)。

一种解决方法是分阶段进行:

prompt# robot --prerunmodifier modifier.MyModifier --pythonpath ./ test.robot
suite keywords - [Custom Suite Setup Keyword]
class          - <class 'robot.running.model.Keyword'>
name           - Custom Suite Setup Keyword
id             - s1-k1
parent(suite)  - Test
timeout        - None
type           - setup
doc            -
tags           - []
children       - []
==============================================================================
Test
==============================================================================
A test                                                                | PASS |
------------------------------------------------------------------------------
Test                                                                  | PASS |
1 critical test,1 passed,0 failed
1 test total,0 failed
==============================================================================

或者,您可能打算用以下内容代替最后一行:

setDT(DT)
DT[,median.height:= median(Height,na.rm = TRUE),by='panelID']
DT[abs(Height - median.height) > 50,newheight:= median.height]
,

尝试:

setDT(DT)
DT[,newheight := ifelse(abs(median(Height,na.rm = TRUE) - Height) > 50,median(Height,Height),by=.(panelID)]