2016-07-21 4 views
1

グループ内(「名前」変数)、値をの四分円にカットします。そして変数 "value"の四分円ラベル列を作成します。グループは、、異なるグループの,のように変化するので、 以下のコードでは、四分位数を全体の値で切り捨てるだけで、と同じ四分円の範囲がすべてのグループに適用されます。さまざまなグループサイズのグループ別ラベル分け

dt<-data.frame(name=c(rep('a',8),rep('b',4),rep('c',5)),value=c(1:8,1:4,1:5)) 
dt 
dt.2<-dt%>% group_by(name)%>% mutate(newcol= 
cut(value,breaks=quantile(value,probs=seq(0,1,0.25),na.rm=TRUE),include.lowest=TRUE)) 
dt.2 
str(dt.2) 

データ:上記のコードから

name value 
1  a  1 
2  a  2 
3  a  3 
4  a  4 
5  a  5 
6  a  6 
7  a  7 
8  a  8 
9  b  1 
10 b  2 
11 b  3 
12 b  4 
13 c  1 
14 c  2 
15 c  3 
16 c  4 
17 c  5 

出力。 更新:問題はnewcolがfactorであるのではなく、necolが異なるグループ全体で同じ四分位範囲を持つことです。たとえば、名前bの場合、値は1-4ですが、四分位範囲は3-5で、グループに関係なくmin(value)からmax(value)に派生します。

name value newcol 
    <fctr> <int> <fctr> 
1  a  1 [1,2] 
2  a  2 [1,2] 
3  a  3 (2,3] 
4  a  4 (3,5] 
5  a  5 (3,5] 
6  a  6 (5,8] 
7  a  7 (5,8] 
8  a  8 (5,8] 
9  b  1 [1,2] 
10  b  2 [1,2] 
11  b  3 (2,3] 
12  b  4 (3,5] 
13  c  1 [1,2] 
14  c  2 [1,2] 
15  c  3 (2,3] 
16  c  4 (3,5] 
17  c  5 (3,5] 

所望の出力

name value newcol/quartile label 

1  a  1 1 
2  a  2 1 
3  a  3 2 
4  a  4 2 
5  a  5 3 
6  a  6 3 
7  a  7 4 
8  a  8 4 
9  b  1 1 
10  b  2 2 
11  b  3 3 
12  b  4 4 
13  c  1 1 
14  c  2 2 
15  c  3 3 
16  c  4 4 
17  c  5 4 
+0

を'cut'の出力が' factor 'なので 'numeric'に強制することができます。つまり' as.numeric(cut(... 'または' findInterval'を使います。 – akrun

+0

@akrun四分位の数値ラベルを取得する方法を指摘してくれてありがとう。しかし、問題はnewcolがすべての異なるグループにわたって同じ四分位範囲を持つことです。それを明確にするために質問を更新します。 – alphabetagamma

答えて

1

はここで、分割適用コンバインの枠組みを以下の、あなたはそれを行うことができます方法です。

dt<-data.frame(name=c(rep('a',8),rep('b',4),rep('c',5)),value=c(1:8,1:4,1:5)) 

split_dt <- lapply(split(dt, dt$name), 
        transform, 
        quantlabel = as.numeric(
cut(value, breaks = quantile(value, probs = seq(0,1,.25)), include.lowest = T))) 

dt <- unsplit(split_dt, dt$name) 

    name value quantlabel 
1  a  1   1 
2  a  2   1 
3  a  3   2 
4  a  4   2 
5  a  5   3 
6  a  6   3 
7  a  7   4 
8  a  8   4 
9  b  1   1 
10 b  2   2 
11 b  3   3 
12 b  4   4 
13 c  1   1 
14 c  2   1 
15 c  3   2 
16 c  4   3 
17 c  5   4 

編集:パフォーマンスが懸念される場合this post

data.table方法があります、私たちは、data.tableパッケージを使用することができます。

library(data.table) 
dt<-data.frame(name=c(rep('a',8),rep('b',4),rep('c',5)),value=c(1:8,1:4,1:5)) 
dt.t <- as.data.table(dt) 
dt.t[,quantlabels := as.numeric(cut(value, breaks = quantile(value, probs = seq(0,1,.25)), include.lowest = T)), name] 

    name value quantlabels 
1: a  1   1 
2: a  2   1 
3: a  3   2 
4: a  4   2 
5: a  5   3 
6: a  6   3 
7: a  7   4 
8: a  8   4 
9: b  1   1 
10: b  2   2 
11: b  3   3 
12: b  4   4 
13: c  1   1 
14: c  2   1 
15: c  3   2 
16: c  4   3 
17: c  5   4 

編集を:とdplyr方法があります

私たちは(私たちは、他のソリューションのために何をやったかである)akrunのアドバイス@従うとas.numericを使用することができます:あなたの代わりにラベルそのものを望んでいた場合、as.characterを使用することを

dt %>% 
    group_by(name) %>% 
    mutate(quantlabel = 
       as.numeric(
        cut(value, 
         breaks = quantile(value, probs = seq(0,1,.25)), 
         include.lowest = T))) 

注:

dt %>% 
    group_by(name) %>% 
    mutate(quantlabel = as.character(cut(value, breaks = quantile(value, probs = seq(0,1,.25)), include.lowest = T))) 

Source: local data frame [17 x 3] 
Groups: name [3] 

    name value quantlabel 
    <fctr> <int>  <chr> 
1  a  1 [1,2.75] 
2  a  2 [1,2.75] 
3  a  3 (2.75,4.5] 
4  a  4 (2.75,4.5] 
5  a  5 (4.5,6.25] 
6  a  6 (4.5,6.25] 
7  a  7 (6.25,8] 
8  a  8 (6.25,8] 
9  b  1 [1,1.75] 
10  b  2 (1.75,2.5] 
11  b  3 (2.5,3.25] 
12  b  4 (3.25,4] 
13  c  1  [1,2] 
14  c  2  [1,2] 
15  c  3  (2,3] 
16  c  4  (3,4] 
17  c  5  (4,5] 
+0

ありがとう!あなたのコードは私のコードとよく似ていて、うまくいきます。しかし、私はなぜここのgroup_byが私のコードを削除することに合格しないのだろうと思っていました。 – alphabetagamma

+0

@Phdaml私は 'dplyr'エキスパートではないので、なぜうまくいかないのか分からない。 – bouncyball

+0

私のグループはなぜ働いていないのか分かりました。私は何とかdplyrパッケージを外しましたが、コードを実行した後にエラーは表示されません。 – alphabetagamma

関連する問題