1

次のようなデータがあります。

Hosp    Score   Var1    Var2    Var3
1       0       5       3       0
1       1       10      8       1
1       2       11      8       2
1       3       5       3       2
2       0       6       4       0
2       2       10      6       1
2       3       10      7       2
3       1       4       3       2
etc...

約 800 の病院と因子スコアの 4 つのレベル (0、1、2、3) があります。一部の病院では、特定のレベルのスコアを観察していません。

変数 Var1、Var2、および Var3 が合計される新しいデータ フレームを生成したいと考えています。したがって、上記のデータを使用すると、

Hosp    Var1    Var2    Var3
1       32      22      5
2       26      17      3
3       4       3       2

これは SQL では些細なことですが (R にもあると思います!)、これまでに見つけた唯一の方法は、Hosp が変更されるたびに新しい行を追加し、変更されていないときに変数をインクリメントするループを使用することです。 (もちろん、データは Hosp でソートされます)。

これを行うための巧妙な方法はありますか?

4

3 に答える 3

4

を使用しaggregate()ます。data.frameあなたの名前が「temp」であると仮定すると、次を使用します。

aggregate(list(Var1 = temp$Var1, Var2 = temp$Var2, Var3 = temp$Var3), 
          list(Hosp = temp$Hosp), sum)
#   Hosp Var1 Var2 Var3
# 1    1   31   22    5
# 2    2   26   17    3
# 3    3    4    3    2

これを行うには、次slickの数式表記を使用しますaggregate()

aggregate(cbind(Var1, Var2, Var3) ~ Hosp, temp, sum)

ただし、デフォルトのメソッドとメソッドNAで値がどのように扱われるかに違いがあることに注意してください。data.frameformula

アップデート

SQLを使用して元の質問で言及しました。SQL の経験はあまりありませんがsqldf、次のことができるパッケージもあります。

sqldf("select Hosp, 
      sum(Var1) `Var1`, sum(Var2) `Var2`, sum(Var3) `Var3` 
      from temp 
      group by Hosp")
#   Hosp Var1 Var2 Var3
# 1    1   31   22    5
# 2    2   26   17    3
# 3    3    4    3    2
于 2012-10-12T10:54:18.500 に答える
3

data.tableメモリ、コーディング、および時間効率のソリューション。

の使用に慣れている場合は、 のビネットを見れば、簡単なSQL構文を見つけることができます。data.tabledata.table

# assuming your data is in DF
library(data.table)
DT <- data.table(DF)

DT[, lapply(.SD, sum), by = hosp, .SDcols = c('Var1', 'Var2', 'Var3')]

この場合、省略形lapply(.SD, FUN), 設定.SDcolsを実行する変数として使用できlapplyます。

より冗長ですがSQL、同じ結果を生成するのに似たアプローチは次のようになります。

DT[, list(Var1 = sum(Var1), Var2 =sum(Var2), Var3 = sum(Var3)), by = hosp]

しかし、必要がないのに、なぜこの余分なコードをすべて書くのでしょうか!

于 2012-10-16T05:27:04.480 に答える
1

mrdwab によるソリューションに基づいて構築しますが、より短い構文を提供します。

aggregate(temp[3:5], temp[1], sum)

これは、データ フレームがリストであるという事実を利用しているため、単一ブラケット サブセットを使用すると、列のサブセットを含むデータ フレームが生成されます。listこれにより、すべての呼び出しが回避されます。


さらに別の選択肢:

library(plyr)
ddply(temp[-2], .(Hosp), colSums, na.rm = TRUE)

これにより、データ フレームが によってチャンクに分割されHosp、そのようなチャンクごとに列の合計が計算されcolSums(chunk, na.rm = TRUE)ます。は入力から列を[-2]削除するScoreため、その合計は得られません。

悲しいかな、以下のコメントで mrdwab が正しく指摘したように、上記もHosp列を合計します。問題に対する私の最初の修正は次のとおりです。

ddply(t[-2], .(Hosp), function(d){colSums(d[-1], na.rm = TRUE)})

Hospこれにより、列が引数から にドロップされるため、デフォルトcolSumsで提供されるその名前の元の列が上書きされません。ddply全体として、もはやきれいな解決策ではなく、速い解決策でもありません。しかし、明示的に綴られたチャンクで動作する関数があるため、非常に柔軟であるため、参照用に残します。

さらに別のコメントで、mrdwab はより良い解決策を提案しました。

ddply(temp[-2], .(Hosp), numcolwise(sum))

numcolwiseに基づく がcolwise内部的に呼び出し、分割の実行に使用された列を削除するため、これは機能します。strip_splitsつまりHosp、この場合です。前の文の関数はすべて から来ていplyrます。

于 2012-10-12T11:43:21.740 に答える