2017-11-09 12 views
0

私は平均と標準偏差のベクトルを持っており、同じプロットでこれらの平均と標準偏差に対応する密度をggplot2でプロットしたいと思います。私はこの問題を解決するためにmapplygatherを使用し、それは私が些細なことだと思います何かのためのコードの行のかなり多くのです:ハードコーディング手段と標準偏差なしでggplot2で複数のノーマルカーブをプロットする

Plot multiple normal curves in same plot

library(dplyr) 
library(tidyr) 
library(ggplot2) 

# generate data 
my_data <- data.frame(mean = c(0.032, 0.04, 0.038, 0.113, 0.105, 0.111), 
         stdev = c(0.009, 0.01, 0.01, 0.005, 0.014, 0.006), 
         test = factor(c("Case_01", "Case_02", "Case_03", "Case_04", 
             "Case_05", "Case_06"))) 

# points at which to evaluate the Gaussian densities 
x <- seq(-0.05, 0.2, by = 0.001) 

# build list of Gaussian density vectors based on means and standard deviations 
pdfs <- mapply(dnorm, mean = my_data$mean, sd = my_data$stdev, MoreArgs = list(x = x), 
       SIMPLIFY = FALSE) 

# add group names 
names(pdfs) <- my_data$test 

# convert list to dataframe 
pdfs <- do.call(cbind.data.frame, pdfs) 
pdfs$x <- x 

# convert dataframe to tall format 
tall_df <- gather(pdfs, test, density, -x) 

# build plot 
p <- ggplot(tall_df, aes(color = test, x = x, y = density)) + 
    geom_line() + 
    geom_segment(data = my_data, aes(color = test, x = mean, y = 0, 
            xend = mean, yend = 100), linetype = "dashed") + 
    coord_cartesian(ylim = c(-1, 100)) 
print(p) 

enter image description hereこれは非常によく似ています

実際には、the accepted answermapplyを使用しているため、正しいトラックにいることがわかります。しかし、私がその答えが気に入らないのは、mapplyコールでハードコードの平均と標準偏差であるということです。私は実際のデータをディスクから読み込むので、私のユースケースではうまくいきません(もちろん、MREでは簡単のためにデータ読み込み部分をスキップしました)。可読性を犠牲にすることなく、mapplyコールで平均と標準偏差ベクトルをハードコーディングすることなく、自分のコードを単純化することは可能ですか?

EDITは多分mapplyへの呼び出しは、パッケージmvtnormを使用することによって回避することができるが、私はそれがここに本当の簡素化をもたらすとは思いません。私のコードのほとんどはmapplyへの呼び出しの後に来ます。

答えて

1

あなたは行が各mean-stdevペアのデータフレームを構成した後に自動的に結合んpurrr::pmap_dfを使用して、いくつかのコーディングを保存することができます:

my_dataが順序またはmean, stdev, testに入力欄があり、testが文字クラスであると仮定。

my_data <- data.frame(mean = c(0.032, 0.04, 0.038, 0.113, 0.105, 0.111), 
         stdev = c(0.009, 0.01, 0.01, 0.005, 0.014, 0.006), 
         test = c("Case_01", "Case_02", "Case_03", "Case_04", "Case_05", "Case_06"), 
         stringsAsFactors = F) 

プロット:

p <- ggplot(tall_df2, aes(color = factor(test), x = x, y = density)) + 
     geom_line() + 
     geom_segment(data = my_data, aes(color = test, x = mean, y = 0, 
             xend = mean, yend = 100), linetype = "dashed") + 
     coord_cartesian(ylim = c(-1, 100)) 

print(p) 

が与える:データ付き

library(purrr) 
tall_df2 <- pmap_df(my_data, ~ data_frame(x = x, test = ..3, density = dnorm(x, ..1, ..2))) 

enter image description here

+0

cool! 'pmap_df'の目標は何ですか?私は 'purrr'に慣れていません – DeltaIV

+0

また、なぜあなたは' ..i' sintaxを使用しなければならないのか分かりません。確かに 'tall_df2 < - pmap_df(my_data、〜data_frame(x = x、test = test、density = dnorm(x、mean、stdev)))'は動作しないので、構文は正しいです。しかし、私がなぜ – DeltaIV

+1

'pmap_df'が' pmap' + 'bind_rows'の組み合わせの並べ替えであるのか、' pmap'は 'mapply'と似ていますが構文は異なっているのは分かりません。 'pmap(list(a、b、c)、f)'を実行する代わりに 'mapply(f、a、b、c)'を実行するのではなく、フレーム。最後に 'do.call(...、rbind)'を保存するために 'bind_rows'を呼び出します。構文の詳細については、 '?pmap'を参照してください。引数を名前で照合したい場合は、明示的に 'pmap_df(my_data、function(mean、stdev、test))data_frame(x = x、test = test、density = dnorm(x、mean、stdev) ) ' – Psidom