6

各列に異なる関数を適用して、時間間隔ごとにデータフレームを集約したいと思います。私はほとんどダウンしていると思います、そして私のデータをパッケージでaggregate間隔に分割しました、それは十分に簡単でした。chron

しかし、サブセットを処理する方法がわかりません。すべてのマッピング関数*apply、、、*plyは1つの関数を取ります(列ごとまたは変数ごとに関数のベクトルを適用するものを期待していましたが、見つかりませんでした)。したがって、データを受け取る関数を作成しています。フレームサブセットであり、インデックスである「time」と合計である「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

それは私が本当に何か間違ったことをしていることを教えてくれます。私がRIについて見てきたことから、これを行うにはエレガントな方法があるはずだと思いますが、それは何ですか?

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")
4

4 に答える 4

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)

その後、試すことができます

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

apply.funユーザー定義関数はどこにありますか。これはかなり批判的なメッセージで失敗しますが、実行中

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

FUN内部の関数aggregateは、データピースごとに1回呼び出される(そしてdata.frameが渡される)のではなく、データピースの列ごとに1回呼び出される(そして名前のないベクトルが渡される)ことを理解するのに役立ちます。を使用して必要な結果を取得しますaggregate

代わりに、パッケージのddply関数を使用できます。plyrそこで、各ピースに適用された関数はdata.frameを受け取るので、次のようなことができます。

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)
}
于 2012-07-22T18:32:58.097 に答える
5

byの代わりに使用してくださいaggregate

fが無名関数と同じである場合、そのlist中が次のように置き換えられることを除いて、次のdata.frameようにf <- function(dat) with(dat, data.frame(...whatever...))なります。

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.)

fだけでなく名前自体を追加した場合は、列名を割り当てる最後のステートメントを削除できますTime

于 2012-07-22T18:36:35.280 に答える
1

これはどう?

library(plyr)
ddply(d., .(time), colMeans)
于 2012-07-22T18:30:51.943 に答える
1

別のオプションは、次のように、aggregate()を交互に実行してからmerge()を使用することにより、ベースRで同じタスクを実行する一連のステップを使用することです。

agMeans_df <- aggregate(cbind(Port.1,Port1.1,Port.2,Port.2.2,Port.3,Port.3.1,Port.4,Port4.1)~timevar,data=d,mean)
agSum_df <- aggregate(Port.5~timevar,data=d,sum)
ag_all_df <- merge(agMeans_df,agSum_df,by="timevar")

グループベクトルは正しいクラス(ここでは「timevar」)である必要があり、列の順序が変更される可能性があるという他の応答で提起された問題について詳しく説明しました。同じ名前の2つの集約された列を混同しないように、同じ列で複数の異なる関数を実行する場合は、merge()の前に名前を変更する必要があります。

于 2018-09-14T22:08:56.583 に答える