R関連‎ > ‎Packages‎ > ‎

plyr

* Plyr.rを読む

データを処理したい単位に切り刻む。
そして、処理をする。
処理したデータを、再整形して、array, list, dataframeに戻す。

関数は、xxplyという命名規則?になる。
最初のx がinputするデータ型( a => array, l => list, d => dataframe)
次のxがoutputするデータ型(上に同じ、_(アンダーバー)だと、ouputなし)
aaply, adply, ddply ldplyとか、、

引数は、 (inputのデータ, データを分割する基準, 分割されたデータを処理する関数)の3つを取る。
4つ目以降は、3つめに入れる関数の引数となる

ddply(diamonds,  .(color), function(df){ price.sum.byColor = sum(df$price)} )
みたいな形。
3つ目の関数の返り値は、設定する?関数に合わせたものにする。
ddplyなら、dataframeを返す。上記の例の場合だと、暗黙の了解で、データフレームのprice.sum.byColor列が付く)



** 操作系関数
*** subset
    sqlのgroup_byしてから、selectするイメージ?
    #select the smallest diamond in each colour
    ddply(diamonds, .(color), subset, carat=min(carat)

    #select the two smallest diamonds
    ddply(diamonds, .(color), subset, order(carat) <=2)

    #select the 1% largest diamonds in each group
    ddply(diamonds, .(color), subset, carat > quantile(carat, 0.99))

    #select all diamonds bigger than the group average
    ddply(diamonds, .(color), subset, price > mean(price))

*** transform
    group別の集計数字を上げて、それを各行に加えるのに便利
    単純なtransformでは面倒だけど、、、という場面に。

    #within each colour, scale price to mean 0 and variable 1
    ddply(diamonds, .(color), transform, price = scale(price))

    #Subtract off group mean
    ddply(diamonds, .(color), transform, price = price - mean(price))




** tutorialをやる。ozoneの変動
  データは、3次元配列(latitude:24levels, longitude:24levels, time:72回by月)
  ozone[1,1,]で、(1,1)での期間の移り変わりがわかる
  time <- 1:72/12 で、一年単位のサイクルを作る


** 注意点
 a(array), l(list), d(dataframe)の略称を使って、関数を命名してる。
 おかげで、とても覚えやすいけど、
 a_plyで、インプットはarrayという事ではない。
 インプットされるデータが、arrayを処理するような形で、まず切り刻まれるという事。
 arrayを処理するような形とは、ある次元を固定して、その単位でデータを切り刻む。
 なので、dataframeでも、行ごとに処理したいとかなら、a_plyとかも使える。

 で、d_plyを処理するような形もあるわけで、これはある列のデータを、値によるグルーピングという切り刻み方。

** aaply
  ほとんどapplyと変わらないけど、arrayで返してくれると嬉しい時もある。
  .drop=Fにしたときの表示が apply より親切
  ??? : idempotentだと。同じarrayで返してくれる。
  marginを指定する => その次元を固定すると頭の中で反芻すると良いかも
  each(min, max)という使い方もある aaply(ozone, 1, each(min,max))
** alply
   リストで返すので、データの塊で返す場合などに使う?例では、テーブルを返す例が表示
   alply(ozone, 3, function(x) table(round(x)))

** arrange
   データフレームの並び替えは mtcars[with(mtcars, order(cyl, disp),] こんな感じらしいけど、
   arrange(mtcars, cyl, disp)とか、arrange(mtcars, cyl, desc(disp)) とかで、できる。
   ただ、帰ってきてデータフレームのrownames(dataframe)が、数字のものに置き換わってしまう。

** as.data.frame
   detailには、This is useful when calling *dply functions with a function that returns a vector, and you want thte output ini rows, rather thatn columns.
   と書いているけど、よく分かってない。試してない。

** as.quoted
   ヘルパー関数みたいなもの?
   called by default on all plyr funcitons that take a .variables argと書いてある。

** a_ply
   ディメンジョンでデータを切って、なんかの処理を副作用的にする。
   使いどころは、今は思い浮かばない

** colwise
   列別に関数を適用したい。関数をラップしてくれるみたい。
   列別のNAの数を調べる
   > nmissing <- function(x)sum(is.na(x)); colwise(nmissing)(baseball)
   年別にNAデータがどこにどれだけあるか調べる
   > ddply(baseball, .(year), colwise(nmissing))
   二番目以降の引数を指定してら、その列名のみに適用
   > ddply(baseball, .(year), colwise(nmissing, .(sb, cs,so)))
   結果のdataframeの列名は、sb, cs, soのみ。
   文字列データでのNAを調べる
   > ddply(baseball, .(year), colwise(nmissing, is.character))
** count
   tableと似てる。as.data.frame(table(x)) と。 zeroカウントをこっちは入れないと書いてある。
   > count(baseball, "id")
   選手別のレコード数
   > count(count(baseball, c("id","year")), "freq")
   選手が同年に複数レコードをもつ(トレードとかで移籍?)数。新しくできるdataframeの列名がfreqなのを利用

** daply
   普通はtapplyを使うような場面は、こちらを使うと良い。
   データフレームがあって、その中のある項目の値について分類して、集計した値を出したい。
   tapplyは集計対象も指定するけど、こっちなら、まとめて集計してくれる。
   > daply(baseball, .(year), mean) これで、すべての項目(year以外)について、year別の平均が出る。
   tapplyのことは忘れるべき。

** dlply

 * splat
   do.callを便利にしたもの? do.callは、一行一行に何かをfunctionさせたい時
   に使う?
   その場合の引数の扱いを、splatは優しくしてくれる。
** each
   複数の関数を包んで関数を返してくれる。返してくれた関数に引数を与えて実行すると、中のそれぞれの関数を処理
   した結果が帰ってくる。
   > each(min, max)(1:10)

** failwith
   処理の結果でエラーになった場合に返す値をいれた形で関数をラップする(定義しなおす)
   > hoge <- function(x) x + 10
   > fn <-  failwith(NULL, hoge);
   > fn(0)
   エラーメッセージが出るが、NULLを受け取って続けられる。

** idata.frame
   実験用機能。data.frameを切り刻むときに、コピーを作るのではなく、参照にとどめておく。効率化が目的。
   > system.time(dlply(baseball, "id", nrow))
   > system.time(dlply(idata.frame(baseball), "id", nrow))

Comments