2012-07-22 5 views
5

データフレームを時間間隔で集計し、各列に異なる関数を適用したいとします。私はほとんどaggregateがダウンしていると思うし、私のデータをchronパッケージで間隔を空けて分けたが、それは十分に簡単だった。R:列固有の関数を持つ集計

しかし、サブセットの処理方法がわかりません。すべてのマッピング関数*apply,*plyは、1つの関数(1つの列または変数を適用する関数のベクトルを取ったが、1つも見つからないものがあると考えていたので)を取るので、私のデータフレームは部分集合であり、インデックスである "時間"とその合計である "Runoff"を除いて、すべての変数の平均値が与えられます。

私はこれを試してみました:それは私に、このエラーを与えていない場合でも、十分な醜いだろう

aggregate(d., list(Time=trunc(d.$time, "00:10:00")), function (dat) with(dat, 
list(Time=time[1], mean(Port.1), mean(Port.1.1), mean(Port.2), mean(Port.2.1), 
mean(Port.3), mean(Port.3.1), mean(Port.4), mean(Port.4.1), Runoff=sum(Port.5)))) 

Error in eval(substitute(expr), data, enclos = parent.frame()) : 
    not that many frames on the stack 

私は本当に何か間違ったことをやっている私に語っています。私がRの見たところから、これを行うにはエレガントな方法が必要だと思いますが、それは何ですか?

dput:これについて

d. <- structure(list(time = structure(c(15030.5520833333, 15030.5555555556, 
15030.5590277778, 15030.5625, 15030.5659722222), format = structure(c("m/d/y", 
"h:m:s"), .Names = c("dates", "times")), origin = structure(c(1, 
1, 1970), .Names = c("month", "day", "year")), class = c("chron", 
"dates", "times")), Port.1 = c(0.359747, 0.418139, 0.417459, 
0.418139, 0.417459), Port.1.1 = c(1.3, 11.8, 11.9, 12, 12.1), 
    Port.2 = c(0.288837, 0.335544, 0.335544, 0.335544, 0.335544 
    ), Port.2.1 = c(2.3, 13, 13.2, 13.3, 13.4), Port.3 = c(0.253942, 
    0.358257, 0.358257, 0.358257, 0.359002), Port.3.1 = c(2, 
    12.6, 12.7, 12.9, 13.1), Port.4 = c(0.352269, 0.410609, 0.410609, 
    0.410609, 0.410609), Port.4.1 = c(5.9, 17.5, 17.6, 17.7, 
    17.9), Port.5 = c(0L, 0L, 0L, 0L, 0L)), .Names = c("time", 
"Port.1", "Port.1.1", "Port.2", "Port.2.1", "Port.3", "Port.3.1", 
"Port.4", "Port.4.1", "Port.5"), row.names = c(NA, 5L), class = "data.frame") 

答えて

8

あなたのアプローチには多くの問題があります。一般的なアドバイスは、最終的なステートメントがどのように見えるかについてはまっすぐに進むのではなく、増分で作業します。そうしないと、デバッグ(エラーの理解と修正)が非常に困難になります。あなたの分割変数に何らかの問題があることに注意することが

aggregate(d., list(Time=trunc(d.$time, "00:10:00")), identity) 

は、たとえば、あなたが開始している可能性があります。明らかにaggregateは、このクラスのデータを扱うのが嫌いです。あなたは、数値にTimeを変換することによってこの問題を解決することができます

aggregate(d., list(Time=as.numeric(trunc(d.$time, "00:10:00"))), identity) 

次にあなたがapply.funは、ユーザー定義関数である

aggregate(d., list(Time=as.numeric(trunc(d.$time, "00:10:00"))), apply.fun) 

を試すことができます。これはかなりcripticメッセージで失敗しますが、aggregate内部FUN機能は、各データピースに1回呼び出さ(およびdata.frameを渡される)されていないことを実現に役立ちます

aggregate(d., list(Time=as.numeric(trunc(d.$time, "00:10:00"))), print) 

を実行しているが、それは、各列に1回呼び出されますあなたのデータピースのうちの1つ(名前のないベクトルを渡したもの)は、aggregateを使用して結果を得る方法がありません。

代わりにplyrパッケージのddply機能を使用できます。そこで、各部分に適用される機能はデータを受け取ります。フレームは、あなたがこのような何かを行うことができますので、:

apply.fun <- function(dat) with(dat, data.frame(Time=time[1], 
               mean(Port.1), 
               mean(Port.1.1), 
               mean(Port.2), 
               mean(Port.2.1), 
               mean(Port.3), 
               mean(Port.3.1), 
               mean(Port.4), 
               mean(Port.4.1), 
               Runoff=sum(Port.5))) 

d.$Time <- as.numeric(trunc(d.$time, "00:10:00")) 
library(plyr) 
ddply(d., "Time", apply.fun) 

#   Time mean.Port.1. mean.Port.1.1. mean.Port.2. mean.Port.2.1. 
# 1 15030.5520833 0.4061886   9.82 0.3262026   11.04 
# mean.Port.3. mean.Port.3.1. mean.Port.4. mean.Port.4.1. Runoff 
# 1  0.337543   10.66  0.398941   15.32  0 

編集:以下の最初のコメントで@roysc質問にフォローアップは、あなたが行うことができます:

apply.fun <- function(dat) { 
    out <- as.data.frame(lapply(dat, mean)) 
    out$Time <- dat$time[1] 
    out$Runoff <- sum(dat$Port.5) 
    return(out) 
} 
+0

大丈夫、私はこれを少し良く理解していると思います。私は強く型付けされた言語に慣れており、Rのクラス強制変換スキームが混乱しているのを発見しています。私が知りたいのは、ほとんどの列の平均を取る単純な方法があるが、それを明示的に行うのではなく、特別に扱うことである。 dfを分離して列を再結合する必要がありますか? – scry

1

どのように?

library(plyr) 
ddply(d., .(time), colMeans) 
+0

これは、列の1つが平均を持つはずではなく、むしろ合計が – Chase

+0

であることに気づきましたが、より有用な回答が出ました。私はこれを更新します。 – Maiasaura

5

利用byの代わりaggregate

fはその後f <- function(dat) with(dat, data.frame(...whatever...))ようにそれがdata.frameに置き換えられ以内にそのlist除いて、無名関数としてsameeの場合:fは名前そのものを追加した場合我々は、列名を割り当て、最後の文を削除することができ

d.by <- by(d., list(Time = trunc(d.$time, "00:10:00")), f) 
d.rbind <- do.call("rbind", d.by) # bind rows together 

# fix up row and column names 
rownames(d.rbind) <- NULL 
colnames(d.rbind) <- colnames(d.) 

ちょうどTimeよりむしろ。