2017-07-27 1 views
1

私は次のようにRで「持っている」データセット、から新しい変数を計算したい:R - (NAが存在する)、グループ化変数に集約うちの1を残す

RE:「R」の値の平均値を特定の観察を除いた所与の「Cat」変数値内にある(注:欠損データが存在し、Rが欠落している場合にREをグループ平均とすることを望む)。

IE:REと同じように、特定の「Cat」変数値内の「I」応答の平均は、特定の観察(同じ欠落データ技術)を除きます。

例示的なデータセットおよび望ましい出力を以下に示します。

を持ち:

ID CAT R I … (Additional variables I need to retain) 
1 1 1 3 … 
2 1 2 NA … 
3 1 1 1 … 
4 2 NA 3 … 
5 2 4 5 … 
6 2 4 NA … 

所望のデータセット( "たい")をすべきである:

はたい:

ID CAT R I RE IE  … (Additional variables retained) 
1 1 1 3 1.5 1  … 
2 1 2 NA 1 2  … 
3 1 1 1 1.5 3  … 
4 2 NA 3 ... ... … 
5 2 4 5    … 
6 2 4 NA    … 

は、特に、以下のSQLベースの溶液は、所望の出力を生成します SASにありますが、Rで動作させることができません(sqldfパッケージを使用しています)。私が知っている1つの問題は、欠落している機能がSAS固有であることです(SQLでは普遍的に利用できません)。これらはすべて、sqldfパッケージを使用したSQLソリューションの出発点として役立つかもしれません。

proc sql; 
create table want as 
select *, 
    (sum(R)-coalesce(R, 0))/(count(R)-1+missing(R)) as RE, 
    (sum(I)-coalesce(I, 0))/(count(I)-1+missing(I)) as IE 
from have 
group by CAT 
order by ID, CAT; 
quit; 

ご協力いただきありがとうございます。

答えて

0

dplyrを使用すると、他の行に影響を与えずに行のサブセットに関数を適用できます。そのドメインの概念をよく知っていればsqlのようなものです。

1つのIDグループに対して目的の計算を実行する関数を作成します。グループ行をgroup_by()でグループ化し、結果をmutate()にパイプしてカスタム関数を実行します。グループ化されたデータでは、一度に1つのグループにしか影響せず、望ましい結果が得られます。

library(dplyr) 

# Data from example 
have <- read.table(header = TRUE, text = 
"ID CAT R I 
1 1 1 3 
2 1 2 NA 
3 1 1 1 
4 2 NA 3 
5 2 4 5 
6 2 4 NA") 

# Create a leave-one-out mean function -- for a single ID group 

leave_one_out_mean <- function(x) { 
    result <- c() 

    for (i in seq_along(x)) { 
     # note minus-i subsetting is used to subset one observation in each iteration 
     # and the na.rm option to handle missing values 
     result[i] <- mean(x[-i], na.rm = TRUE) 
    } 

    return(result) 
} 

# Use group by but _do not_ pipe the result through summarize() 

want <- have %>% 
    group_by(CAT) %>% 
    mutate(RE = leave_one_out_mean(R), 
      IE = leave_one_out_mean(I)) 

結果は

want 

Source: local data frame [6 x 6] 
Groups: CAT [2] 

    ID CAT  R  I RE IE 
    <int> <int> <int> <int> <dbl> <dbl> 
1  1  1  1  3 1.5  1 
2  2  1  2 NA 1.0  2 
3  3  1  1  1 1.5  3 
4  4  2 NA  3 4.0  5 
5  5  2  4  5 4.0  3 
6  6  2  4 NA 4.0  4 

forループが適用機能で置き換えることができますが、私はそれをロジックをハイライトではなく、実行を最適化するには、この方法を書きました。

+0

ありがとうございます。最適化された実行のためにapply関数を使用してデモンストレーションすることもできますか? – Justin

+0

私は頭に入れていたのは、関数の本体を 'sapply(seq_along(x)、function(i)mean(x [-i]、na.rm = TRUE))'に置き換えることでした。それは実際には高速です – Damian

1

SQLコードに触発されたループのないベースRソリューション。

d <- read.table(text = 
'ID CAT R I 
1 1 1 3 
2 1 2 NA 
3 1 1 1 
4 2 NA 3 
5 2 4 5 
6 2 4 NA', header = TRUE) 

myfunc <- function(x) { 
    tmp <- x ; tmp[is.na(tmp)] <- 0 
    ((sum(x, na.rm = TRUE)-tmp)/(length(x[!is.na(x)])-1 + is.na(x))) 
} 
RE <- as.vector(t(aggregate(d["R"], d["CAT"], myfunc)$R)) 
IE <- as.vector(t(aggregate(d["I"], d["CAT"], myfunc)$I)) 

cbind(d, RE, IE) 
+0

また、私はcbindで何かを持っていたに違いないが、有用な解決策は、データセットが参加していない。 – Justin

関連する問題