检测宽数据帧上的异常值

use*_*980 4 r

X

Team Date       Score
A    1-1-2012   80
A    1-2-2012   90
A    1-3-2012   50
A    1-4-2012   40   
B    1-1-2012   100
B    1-2-2012   60
B    1-3-2012   30
B    1-4-2012   70
etc
Run Code Online (Sandbox Code Playgroud)

我需要并且可以将此数据框转换为每个团队的一行宽数据框,并将所有观察和日期作为标题:

XX

Team 1-1-2012 1-2-2012  1-3-2012 1-4-2012
A    80       90        50        40
B    100     60         30        70  
Run Code Online (Sandbox Code Playgroud)

我需要计算每行的均值和sd,我可以这样做:

XX

Team 1-1-2012 1-2-2012  1-3-2012 1-4-2012  mean   sd
A    80       90        50        40       75    20
B    100     60         30        70       55    10 
Run Code Online (Sandbox Code Playgroud)

考虑到我在数据帧xx中有数千行.我想对每个单元格进行计算,如下所示:

如果abs(xx-Mean)> 3*SD,则创建计数器列名称并递增该值.这个想法是将每个观察值与平均值和sd进行比较,如果给定团队的每个观察值与此匹配 - abs(xx-Mean)> 3*SD,则递增计数器.在检查每个单元格之后,我想查看每个团队的每个计数器,并获得具有最高计数器值的前十名高级团队.基本上我试图检测最多的异常值.一旦我获得前10名团队名称,我想在数据框x上绘制他们的时间序列数据.

我希望我不会让它变得比它应该更复杂.不确定,R已经具有对每个单元格进行计算的功能.如何实现这一点的任何想法表示赞赏?

Cha*_*ase 6

我会以长格式保留您的数据并使用plyr,data.table或使用任何其他拆分应用组合工具来计算您的统计数据.这是我plyr用于任务的方式:

#Your data
dat <- read.table(text = "Team Date       Score
A    1-1-2012   80
A    1-2-2012   90
A    1-3-2012   50
A    1-4-2012   40   
B    1-1-2012   100
B    1-2-2012   60
B    1-3-2012   30
B    1-4-2012   70", header = TRUE)

library(plyr)

#Compute mean and sd by team
dat <- ddply(dat, .(Team), transform, mean = mean(Score), sd = sd(Score))
#Your outlier threshold
dat <- transform(dat, outlier = abs(Score - mean) > 3*sd)
#Cumulative sum by team
dat <- ddply(dat, .(Team), transform, cumsumOutlier = cumsum(outlier))
Run Code Online (Sandbox Code Playgroud)

给你这个输出(它与你的例子不符,但可能是你的真实数据):

 Team     Date Score mean       sd outlier cumsumOutlier
1    A 1-1-2012    80   65 23.80476   FALSE             0
2    A 1-2-2012    90   65 23.80476   FALSE             0
3    A 1-3-2012    50   65 23.80476   FALSE             0
4    A 1-4-2012    40   65 23.80476   FALSE             0
5    B 1-1-2012   100   65 28.86751   FALSE             0
6    B 1-2-2012    60   65 28.86751   FALSE             0
7    B 1-3-2012    30   65 28.86751   FALSE             0
8    B 1-4-2012    70   65 28.86751   FALSE             0
Run Code Online (Sandbox Code Playgroud)

  • 提示有人带来一些计时结果...`data.table`将赢得那场战斗,这里有一些[证明](http://stackoverflow.com/questions/10748253/idiomatic-r-code-for-partitioning-a维矢量逐一个指数和 - 执行-AN-operati/10748470#10748470) (2认同)

mne*_*nel 5

A long-format,data.table方法

DT <- read.table( 'clipboard', header = T)
library(data.table)
DT <- as.data.table(DT)
DT[, mean.score := mean(Score), by = Team]
##    Team     Date Score mean.score
## 1:    A 1-1-2012    80         65
## 2:    A 1-2-2012    90         65
## 3:    A 1-3-2012    50         65
## 4:    A 1-4-2012    40         65
## 5:    B 1-1-2012   100         65
## 6:    B 1-2-2012    60         65
## 7:    B 1-3-2012    30         65
## 8:    B 1-4-2012    70         65
DT[, sd.score := sd(Score), by = Team]
##    Team     Date Score mean.score sd.score
## 1:    A 1-1-2012    80         65 23.80476
## 2:    A 1-2-2012    90         65 23.80476
## 3:    A 1-3-2012    50         65 23.80476
## 4:    A 1-4-2012    40         65 23.80476
## 5:    B 1-1-2012   100         65 28.86751
## 6:    B 1-2-2012    60         65 28.86751
## 7:    B 1-3-2012    30         65 28.86751
## 8:    B 1-4-2012    70         65 28.86751
DT[, outlier := abs(Score-mean.score) > 3 * sd.score, by = Team]
##    Team     Date Score mean.score sd.score outlier
## 1:    A 1-1-2012    80         65 23.80476   FALSE
## 2:    A 1-2-2012    90         65 23.80476   FALSE
## 3:    A 1-3-2012    50         65 23.80476   FALSE
## 4:    A 1-4-2012    40         65 23.80476   FALSE
## 5:    B 1-1-2012   100         65 28.86751   FALSE
## 6:    B 1-2-2012    60         65 28.86751   FALSE
## 7:    B 1-3-2012    30         65 28.86751   FALSE
## 8:    B 1-4-2012    70         65 28.86751   FALSE
Run Code Online (Sandbox Code Playgroud)

或者,只需一步

DT[, outlier := abs(Score-mean(Score)) > 3 *  sd(Score), by = Team]
Run Code Online (Sandbox Code Playgroud)

添加异常值的数量(逻辑变量的总和将强制为0,1)

DT[, sum.outlier := sum(outlier), by = Team]
Run Code Online (Sandbox Code Playgroud)