2012-01-12 13 views
2

Rのループに関係するすべての質問は、「ループが悪い」、「あなたは間違っています」というメッセージが表示され、listまたはtapplyまたはそれ以外のものを使用するようにアドバイスしているようです。これはループの有効な実装ですか?

私はRを学んでいる、と因子レベルの#が、私はそれを実行するたびに変更することで、各因子のレベルのためのイメージファイルを作成するには、次のループを実装している:

for(i in unique(df$factor)) { 
    lnam <- paste("test_", i, sep="") 
    assign(lnam, subset(df, factor==i)) 
    lfile <- paste(lnam, ".png", sep="") 
    png(file = lfile, bg="transparent") 
     with(get(lnam), hist(x, main = paste("Histogram of x for ", i, " factor", sep=""))) 
    dev.off() 
} 

これは動作します。私はおそらくそれらのサブグループ(ファイルに出力される)に対してさまざまなテストを実行するためにそれを拡張したいと思っています。

これは有効かつ正当なループの使用ですか?または、この猫に皮膚をかけるための好ましい方法はありますか?

答えて

7

一般的にループに問題はありません。場合によっては、出力よりもむしろ副作用のためにファイルや関数を呼び出すときには、ループを*apply呼び出しよりも簡単に実行することができます。しかし、ループを使用してベクトル化できる演算をシミュレートすると、それはしばしばはるかに遅くなるため、回避することを推奨します。

あなたの具体的な例として再、しかし、私は次のようなコメントを作ると思います:

  • をあなたが要因の各レベルのために何かをしたい場合は、それがlevels(factor)ではなくunique(factor)を使用する方が簡単です。
  • ファクタレベルごとに新しいデータフレームを作成する必要はありません。念頭に置いて

:この場合

for(i in levels(df$factor)) 
{ 
    lf <- paste("test_", i, ".png", sep="") 
    png(file=lf, bg="transparent", 
     with(subset(df, factor == i), hist(x, ....) 
    dev.off() 
} 
+3

また、ループの外側で 'paste'関数を使うこともできます。 – csgillespie

+0

ありがとう - 簡素化は理にかなっています。私は、生成されたデータフレームに他の "魔法"を実行しているかもしれません... @ ccsgillespieあなたのコメントは私を混乱させます。 – Trees4theForest

+0

'lf = paste(" test_ "、levels(df $ factor)、" .png "、sep =" "'のようなものです。もちろん、あなたは ''私は何を繰り返しているかを変更する必要があります。この場合、それはあなたが行く道を変えることはありません。 – csgillespie

4

、合理的なオプションは、データフレームのリストにあなたのデータフレームに変換するために、特定の因子レベルでの各含むサブセットをsplitを使用することです。

split_df <- split(df, df$factor) 

コリンが述べたように、pasteをベクトル化することができますので、あなたは一度だけ、それを呼び出す必要があります。

lfile <- paste("test_", names(split_df), ".png", sep = "") 

すべてのプロットコードを関数にグループ化します。 (私たちは2つの入力を必要とするので、この場合mapplyで)

draw_and_save_histogram <- function(data, file) 
{ 
    png(file) 
    with(data, hist(x)) 
    dev.off() 
} 

今、あなたは、より簡単に、プレーンループと*apply機能の違いを比較することができます。むしろ別のファイルに保存するヒストグラムの抽選より

for(i in seq_along(split_df)) 
{ 
    draw_and_save_histogram(split_df[[i]], lfile[i]) 
} 

mapply(
    draw_and_save_histogram, 
    split_df,  
    lfile  
) 

、それはlatticeまたはggplot2を使用して、いくつかのパネルで1つのプロットを描画するためにはるかに望ましいです。

library(lattice) 
histogram(~ x | factor, df) 

library(ggplot2) 
ggplot(df, aes(x)) + geom_histogram() + facet_wrap(~ factor) 
+0

私は「分裂」を知っていませんでした。素敵な方法です。「1つのプロットを描くことがより好ましい」ということは、すべてあなたの必要に応じて決まると思います。実際に、ループ内で格子を使用して、出力のために別々のファイルに入力が必要ですが、同じ質問があると思う人にとっては良い指導になります。 – Trees4theForest

関連する問題