2011-06-03 26 views
3

我想在這樣的數據幀進行極值調整:Winsorize數據框中

event_date beta_before  beta_after 
2000-05-05 1.2911707054 1.3215648954 
1999-03-30 0.5089734305 0.4269575657 
2000-05-05 0.5414700258 0.5326762272 
2000-02-09 1.5491034852 1.2839988507 
1999-03-30 1.9380674599 1.6169735009 
1999-03-30 1.3109909155 1.4468207148 
2000-05-05 1.2576420753 1.3659492507 
1999-03-30 1.4393018341 0.7417777965 
2000-05-05 0.2624037804 0.3860641307 
2000-05-05 0.5532216441 0.2618245169 
2000-02-08 2.6642931822 2.3815576738 
2000-02-09 2.3007578964 2.2626960407 
2001-08-14 3.2681270302 2.1611010935 
2000-02-08 2.2509121123 2.9481325199 
2000-09-20 0.6624503316 0.947935581 
2006-09-26 0.6431111805 0.8745333151 

通過極值調整我的意思是找到最大和最小的beta_before例如。應該用相同列中的第二高或第二低值替換該值,而不會丟失觀察中的其餘細節。例如。在這種情況下,在beta_before之前,最大值爲3.2681270302,應該由3.2681270302替換。 min和beta_after變量將遵循相同的過程。因此,每列只有2個值會發生變化,最高和最低,其餘部分保持不變。

有什麼建議嗎?我在plyr嘗試了不同的方法,但我最終取代了我不想做的整個觀察。我想創建2級新的變量,例如beta_before_winsorized和β_after_winsorized

+2

這倒不決策意識。你之前和之後的最大值是相同的。我也對使用plyr感到困惑。你是否按日期進行某種類型的分組? Plyr是分裂,應用和組合的工具。我無法分辨你的分裂在這裏。 – 2011-06-03 16:59:57

+0

@JD龍。這只是實際數據框的一個子集。實際的數據幀包含具有不同值的另一列。不同的「事件」由兩個變量的組合組成,因此,'plyr'對我來說很有用。我在描述中犯了一個錯誤,之前和之後的值都不一樣。感謝您的評論,並對此感到抱歉。 – ASC 2011-06-16 16:40:28

回答

5

這裏是一個函數,它的winsorzation你描述:

winsorize <- function(x) { 
    Min <- which.min(x) 
    Max <- which.max(x) 
    ord <- order(x) 
    x[Min] <- x[ord][2] 
    x[Max] <- x[ord][length(x)-1] 
    x 
} 

如果你的數據在數據幀dat,那麼我們就可以

dat2 <- dat 
dat2[, -1] <- sapply(dat[,-1], winsorize) 

導致:

R> dat2 
    event_date beta_before beta_after 
1 2000-05-05 1.2911707 1.3215649 
2 1999-03-30 0.5089734 0.4269576 
3 2000-05-05 0.5414700 0.5326762 
4 2000-02-09 1.5491035 1.2839989 
5 1999-03-30 1.9380675 1.6169735 
6 1999-03-30 1.3109909 1.4468207 
7 2000-05-05 1.2576421 1.3659493 
8 1999-03-30 1.4393018 0.7417778 
9 2000-05-05 0.5089734 0.3860641 
10 2000-05-05 0.5532216 0.3860641 
11 2000-02-08 2.6642932 2.3815577 
12 2000-02-09 2.3007579 2.2626960 
13 2001-08-14 2.6642932 2.1611011 
14 2000-02-08 2.2509121 2.3815577 
15 2000-09-20 0.6624503 0.9479356 
16 2006-09-26 0.6431112 0.8745333 
通過使用你的程序windsoroize數據

我不知道你在哪裏得到了你建議的值應該代替beta_before中的最大值,作爲第二高的2.6642932在提供的數據片段中,這就是我的函數用來代替最大值的值。

請注意,由於which.min()which.max()被記錄爲工作方式,因此每個列中分別有一個最小值和最大值時,該功能纔有效。如果你有多個條目採取同樣的最大值或最小值那麼我們就需要不同的東西:

winsorize2 <- function(x) { 
    Min <- which(x == min(x)) 
    Max <- which(x == max(x)) 
    ord <- order(x) 
    x[Min] <- x[ord][length(Min)+1] 
    x[Max] <- x[ord][length(x)-length(Max)] 
    x 
} 

應該這樣做(後者未測試)。

+0

完全按照需要工作。大!現在顯而易見,我知道答案! – ASC 2011-06-03 17:08:16

7

我認爲winsorizing通常會從有序列表的底部找到值x%(通常爲10%,15%或20%),並用該值替換其下的所有值。與頂部相同。在這裏,您只是選擇頂部和底部值,但winsorizing通常涉及指定頂部和底部的值的百分比來替換。

0

從我以前的點跟進有關與價值在調整位置在實際更換待修整值:

winsorized.sample<-function (x, trim = 0, na.rm = FALSE, ...) 
{ 
    if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) { 
    warning("argument is not numeric or logical: returning NA") 
    return(NA_real_) 
    } 
    if (na.rm) 
    x <- x[!is.na(x)] 
    if (!is.numeric(trim) || length(trim) != 1L) 
    stop("'trim' must be numeric of length one") 
    n <- length(x) 
    if (trim > 0 && n) { 
    if (is.complex(x)) 
     stop("trimmed sample is not defined for complex data") 
    if (any(is.na(x))) 
     return(NA_real_) 
    if (trim >= 0.5) { 
     warning("trim >= 0.5 is odd...trying it anyway") 
    } 
    lo <- floor(n * trim) + 1 
    hi <- n + 1 - lo 
    #this line would work for just trimming 
    # x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi] 
    #instead, we're going to replace what would be trimmed 
    #with value at trim position using the next 7 lines 
    idx<-seq(1,n) 
    myframe<-data.frame(idx,x) 
    myframe<-myframe[ order(x,idx),] 
    myframe$x[1:lo]<-x[lo] 
    myframe$x[hi:n]<-x[hi] 
    myframe<-myframe[ order(idx,x),] 
    x<-myframe$x 
    } 
    x 
} 
#test it 
mydist<-c(1,20,1,5,2,40,5,2,6,1,5) 
mydist2<-winsorized.sample(mydist, trim=.2) 
mydist 
mydist2 
descStat(mydist) 
descStat(mydist2) 
2

嚴格地說,「極值調整」是更換最極端的數據點的行爲一個可接受的百分位數(正如其他一些答案中提到的)。一個相當標準的R功能是psych包中的winsor。嘗試:

dat$beta_before = psych::winsor(dat$beta_before, trim = 0.0625) 
dat$beta_after = psych::winsor(dat$beta_after , trim = 0.0625) 

我選擇trim =是0.0625(該6.25th百分點和93.75th百分點),因爲你只有16個數據點,你想「收服」的頂部和底部的:1/16 = 0。0625

請注意,這可能會使極端數據等於數據集中可能存在或可能不存在的百分位數:數據的理論第n百分位數。

1

statar包對此非常有效。自述文件中複製有關片段:

# winsorize (default based on 5 x interquartile range) 
v <- c(1:4, 99) 
winsorize(v) 
winsorize(v, replace = NA) 
winsorize(v, probs = c(0.01, 0.99)) 
winsorize(v, cutpoints = c(1, 50)) 

https://github.com/matthieugomez/statar