2016-06-23 5 views
-2

私は、名前column.Itの値に基づいてデータのサブセットを取る関数を記述しました。列 "mark"の外れ値を計算し、すべての外れ値を置き換えます。 しかし、これらの異なるサブセットを結合しようとすると、要素の順序が変わります。rでbyとrbind関数を使用するときに行の要素の順序を維持する方法はありますか?

name mark 
    A 100.0 
    B 0.5 
    C 100.0 
    A 50.0 
    B 90.0 
    B 1000.0 
    C 1200.0 
    C 5000.0 
    A 210.0 

私が書かれている機能は次のとおりです:

data.frame(do.call("rbind", as.list(by(data, data$name, 
    function(x){apply(x[, .(mark)],2, 
    function(y) {y[y > (quantile(x$mark, na.rm=TRUE)[[3]][[1]] + 1.5 * IQR(x$mark))] 
    <- (quantile(x$mark, na.rm=TRUE)[[3]][[1]] + 1.5 * IQR(x$mark));y})})))) 
私はコラム「マーク」で私の要素の順序を維持することが可能な任意の方法は、私のデータセットがある

あります

上記の関数の結果は、下の最初の列です(図の目的で手動でnameを追加しました)。

 mark  NAME 
100.000 ----- A 
50.000 ----- A 
210.000 ----- A 
0.500 ----- B 
90.000 ----- B 
839.625 ----- B 
100.000 ----- C 
1200.000 ----- C 
4875.000 ----- C 

上記の結果では、マーク列の値の順序が変更されています。要素の順序を維持する方法はありますか?

+0

なぜあなたは '内apply'必要がありますか? – HubertL

答えて

1

コードがあなたの考えをしていると確信していますか?

メジアン(第3の返された値quantile)より大きい値をメジアン+ 1.5 * IQRに置き換えているようです。たぶんそれがあなたの意図している、私は知らない。より大きな問題は、apply関数でそれをやっていることです。そのため、それはすでに変更されている前の行で更新された各繰り返しとその中央値とIQRを再計算します。私はあなたが望むものではない賭けたいだろうが、私は見知らぬ人を見たと思う。

より良いオプションは、すべてのデータを取り込み、計算してすべてのデータを出力する作業を行う外部関数を作成することです。私はdplyrがきれいだからこそ簡単です。 (?なぜ「----」)

scores <- read.table(text=" 
name mark 
A 100.0 
B 0.5 
C 100.0 
A 50.0 
B 90.0 
B 1000.0 
C 1200.0 
C 5000.0 
A 210.0", header=TRUE) 

ともう少し賢明な何かをする関数を作成するには、あなたのデータを読み込み

dplyr::mutateに(あなたはそれが何であるかを知っているので、名前で参照)の75%分位以上、この処理の連鎖その制限値

scale_outliers <- function(data) { 

    lim <- quantile(data, na.rm = TRUE) 
    data[data > lim["75%"]] <- lim["75%"] 
    data[data < lim["25%"]] <- lim["25%"] 
    return(data) 

} 

と25%分位未満の任意の値がきちんとされ、その後、することができ置き換えますggplotに渡されました。ここでは、元のデータ

gg1 <- scores %>% ggplot(aes(x=name, y=mark)) 
gg1 <- gg1 + geom_point() + geom_boxplot() + coord_cartesian(ylim=range(scores$mark)) 
gg1 

gg1

そして、我々は、新しい機能とそれを変更した場合、行が周り

scores %>% mutate(new_mark = scale_outliers(mark)) 
#> name mark new_mark 
#> 1 A 100.0  100 
#> 2 B 0.5  90 
#> 3 C 100.0  100 
#> 4 A 50.0  90 
#> 5 B 90.0  90 
#> 6 B 1000.0  1000 
#> 7 C 1200.0  1000 
#> 8 C 5000.0  1000 
#> 9 A 210.0  210 

を変更し、私たちがプロットすることができずに、我々は戻ってデータを取得します、その

gg2 <- scores %>% mutate(new_mark = scale_outliers(mark)) %>% ggplot(aes(x=name, y=new_mark)) 
gg2 <- gg2 + geom_point() + geom_boxplot() + coord_cartesian(ylim=range(scores$mark)) 
gg2 

gg2

すべてのベスト、あなたは今、(少しリファクタリングバージョンクォン比較群ごとの言う、name列で、それは、dplyr::group_by(name)を使用するのと同じくらい簡単だ

gg3 <- scores %>% group_by(name) %>% mutate(new_mark = scale_outliers(mark)) %>% ggplot(aes(x=name, y=new_mark)) 
gg3 <- gg3 + geom_point() + geom_boxplot() + coord_cartesian(ylim=range(scores$mark)) 
gg3 

gg3

0

ことを行いたい場合ハック-Rの答えを - あなたのdata.tableにインデックスを追加することができます

data <- data.table(name = c("A", "B","C", "A","B","B","C","C","A"),mark = c(100,0.5,100,50,90,1000,1200,5000,210)) 
data[,i:=.I] 

次に、あなたの計算を実行していますが、Tを保ちます彼namei

df <- data.frame(do.call("rbind", as.list(
    by(data, data$name, 
     function(x) cbind(i=x$i, 
        name=x$name, 
        apply(x[, .(mark)], 2,function(y) {y[y > (quantile(x$mark, na.rm=TRUE)[[3]][[1]] + 1.5 * IQR(x$mark))] <- (quantile(x$mark, na.rm=TRUE)[[3]][[1]] + 1.5 * IQR(x$mark));y}) 
        ))))) 

そして最後に、あなたは、インデックスを使用して順序を:

df[order(df$i),] 
    i name mark 
1 1 A  100 
4 2 B  0.5 
7 3 C  100 
2 4 A  50 
5 5 B  90 
6 6 B 839.625 
8 7 C 1200 
9 8 C 4875 
3 9 A  210 
関連する問題