2017-05-08 18 views
3

は例を見てみましょう:同じ列で異なる行の値に基づいて列の値を更新するにはどうすればよいですか?

> set.seed(42) 
> ids <- c("u1", "u2", "u3") 
> groups <- c(rep("A",3), rep("B",3), rep("C",3)) 
> reps <- c(rep("r1",9), rep("r2",9), rep("r3",9)) 
> vals <- rnorm(27, 0, 2) 
> 
> df = data.frame(ids = rep(ids, 9), groups = rep(groups,3), reps = reps, vals = vals) 
> df 
    ids groups reps  vals 
1 u1  A r1 2.7419169 
2 u2  A r1 -1.1293963 
3 u3  A r1 0.7262568 
4 u1  B r1 1.2657252 
5 u2  B r1 0.8085366 
6 u3  B r1 -0.2122490 
7 u1  C r1 3.0230440 
8 u2  C r1 -0.1893181 
9 u3  C r1 4.0368474 
10 u1  A r2 -0.1254282 
11 u2  A r2 2.6097393 
12 u3  A r2 4.5732908 
13 u1  B r2 -2.7777214 
14 u2  B r2 -0.5575775 
15 u3  B r2 -0.2666427 
16 u1  C r2 1.2719008 
17 u2  C r2 -0.5685058 
18 u3  C r2 -5.3129108 
19 u1  A r3 -4.8809339 
20 u2  A r3 2.6402267 
21 u3  A r3 -0.6132772 
22 u1  B r3 -3.5626169 
23 u2  B r3 -0.3438347 
24 u3  B r3 2.4293494 
25 u1  C r3 3.7903869 
26 u2  C r3 -0.8609383 
27 u3  C r3 -0.5145388 

は、私は何をしたいIDごとにC.r1、C.r2とC.r3内の値の平均値を減算することです。この考え方は、グループCを他のグループのベースラインとして使用することです。

そこで期待される結果の観点から、最初の2行分の:

  • (U1、A、R1)が2.74のように変更しなければならない - 平均(3.02、1.27、3.79)= 0.046

  • (U2、A、R1)は-1.23のように変更する必要がある - 平均(-0.18、-0.56、-0.86)= -0.69

どのように私は、これは内のすべての行で動作するように取得することができます大関連するもの以外に多数の他の列を含むe(約1M行)テーブル?私は明らかにidsでグループ化する必要がありますが、具体的にはgroup == Cと一致する値の検索は、valの平均とともに少しトリッキーです。

> dt <- setDT(df) 
> dt[groups == "C", cmean := mean(vals), ids] 

は私に(複数のコピーで)各IDのグループCの測定の手段を与えるが、他のすべての行が既に除外されているので、私は本当に、すぐにそれらの値を使用することはできません。私は何とか連鎖する必要があるかもしれないと思うが、私はどのように正確にはわからない。

私たちは「IDS」によってグループ化された「C」、ある「グループ」のサブセット化した後に参加を行うことができますdata.tabledplyr

答えて

1

とソリューションで均等に興味がある、「ヴァルス」のmeanを取得し、その後、我々は、元のデータセットon「IDを」参加、第から「Meanvals」と第一のデータセットから「ヴァルス」を減算し、それを(:=)を割り当てる「newvals」

setDT(df)[df[groups=="C", .(Meanvals = mean(vals)), ids], 
         newvals := vals - Meanvals, on = .(ids)] 
head(df) 
+0

これはうまくいきますが、理由はわかりません。少し説明できますか?この場合、「サブセット化」はdata.tableを返しませんか?同じデータテーブルインデックスの 'i'文の中でdata.tableをどのように使うことができますか? – posdef

+0

@posdefはい、それをサブセット化しますが、元のデータセットと 'ids'で 'on 'を結合するとき、' Mean 'は対応する' ids 'ごとに繰り返され、これを減算することができます。ここで、 'X [Y、on =。(grouping variable)]' – akrun

+0

を使って元のテーブル 'dt'を修正し、修正されたコピーを' dplyr'で返すことは可能でしょうか? – posdef

1

一つdplyr可能 - ソリューション:

library(dplyr) 
df %>% group_by(ids) %>% 
    mutate(mean = mean(vals[groups=="C"]), 
     vals = vals - mean) %>% select(-mean) 

# A tibble: 27 × 4 
     ids groups reps  vals 
    <fctr> <fctr> <fctr>  <dbl> 
1  u1  A  r1 0.04680632 
2  u2  A  r1 -0.58980895 
3  u3  A  r1 1.32312422 
4  u1  B  r1 -1.42938536 
5  u2  B  r1 1.34812404 
関連する問題