50

ggplotを使用して複数の列をループし、複数のプロットを作成したいのですが、forループでプレースホルダーを使用すると、ggplotの動作が変わります。

私がこれを持っている場合:

t <- data.frame(w = c(1, 2, 3, 4), x = c(23,45,23, 34), 
y = c(23,34,54, 23), z = c(23,12,54, 32))

これは正常に機能します。

ggplot(data=t, aes(w, x)) + geom_line()

しかし、これはしません:

i <- 'x'
ggplot(data=t, aes(w, i)) + geom_line()

最終的にx、y、zをループしたい場合、これは問題です。何か助けはありますか?

4

4 に答える 4

60

次のように、aes_stringの代わりに使用する必要があります。aes

ggplot(data=t, aes_string(x = "w", y = i)) + geom_line() 

wその場合も文字列として指定する必要があることに注意してください。

于 2011-01-31T22:41:42.317 に答える
25

ggplot2 > 3.0.0きちんとした評価代名詞をサポートします.data。したがって、次のことができます。

  • x列とy列の名前を入力として受け取る関数を作成します。の使用に注意してください.data[[]]

  • 次に、を使用してすべての列をループしますpurrr::map

library(rlang)
library(tidyverse)

dt <- data.frame(
  w = c(1, 2, 3, 4), x = c(23, 45, 23, 34),
  y = c(23, 34, 54, 23), z = c(23, 12, 54, 32)
)

文字列を入力として受け入れる関数を定義する

plot_for_loop <- function(df, x_var, y_var) {
  
  ggplot(df, aes(x = .data[[x_var]], y = .data[[y_var]])) + 
    geom_point() + 
    geom_line() +
    labs(x = x_var, y = y_var) +
    theme_classic(base_size = 12)
}

すべての列をループします

plot_list <- colnames(dt)[-1] %>% 
  map( ~ plot_for_loop(dt, colnames(dt)[1], .x))

# view all plots individually (not shown)
plot_list

# Combine all plots
library(cowplot)
plot_grid(plotlist = plot_list,
          ncol = 3)

編集:上記の関数はrlang::sym!!(bang bang)で書くこともできます。

plot_for_loop2 <- function(df, .x_var, .y_var) {
  
  # convert strings to variable
  x_var <- sym(.x_var)
  y_var <- sym(.y_var)
  
  # unquote variables using !! 
  ggplot(df, aes(x = !! x_var, y = !! y_var)) + 
    geom_point() + 
    geom_line() +
    labs(x = x_var, y = y_var) +
    theme_classic(base_size = 12)
}

または、データフレームをワイド形式からロング形式に変換した後にfacet_grid/facet_wraptidyr::gatherを使用することもできます( )

dt_long <- dt %>% 
  tidyr::gather(key, value, -w)
dt_long
#>    w key value
#> 1  1   x    23
#> 2  2   x    45
#> 3  3   x    23
#> 4  4   x    34
#> 5  1   y    23
#> 6  2   y    34
#> 7  3   y    54
#> 8  4   y    23
#> 9  1   z    23
#> 10 2   z    12
#> 11 3   z    54
#> 12 4   z    32

### facet_grid
ggp1 <- ggplot(dt_long, 
       aes(x = w, y = value, color = key, group = key)) +
  facet_grid(. ~ key, scales = "free", space = "free") +
  geom_point() + 
  geom_line() +
  theme_bw(base_size = 14)
ggp1

### facet_wrap
ggp2 <- ggplot(dt_long, 
       aes(x = w, y = value, color = key, group = key)) +
  facet_wrap(. ~ key, nrow = 2, ncol = 2) +
  geom_point() + 
  geom_line() +
  theme_bw(base_size = 14)
ggp2

### bonus: reposition legend
# https://cran.r-project.org/web/packages/lemon/vignettes/legends.html
library(lemon)
reposition_legend(ggp2 + theme(legend.direction = 'horizontal'), 
                  'center', panel = 'panel-2-2')

于 2018-08-27T19:10:28.057 に答える
3

問題は、データフレームにアクセスする方法ですt。ご存知かもしれませんが、これを行うにはいくつかの方法がありますが、残念ながら、キャラクターを使用することは明らかにその1つではありませんggplot

うまくいく1つの方法は、例の列の数値位置を使用することです。たとえば、を試すことができますi <- 2。ただし、これが機能する場合は、私が使用したことのないggplotに基づいています(ただし、Hadleyによる他の作業を知っているので、機能するはずです)

これを回避する別の方法は、ggplotを呼び出すたびに新しい一時データフレームを作成することです。例えば:

tmp <- data.frame(a = t[['w']], b = t[[i]])
ggplot(data=tmp, aes(a, b)) + geom_line()
于 2011-01-31T22:42:08.167 に答える
1

あなたがやろうとしていることに応じて、私は同じ基本構造で複数のプロットを作成するためにうまくいくfacet_wrapか、うまくいくでしょう。facet_gridこのような何かがあなたを正しい球場に連れて行くはずです:

t.m = melt(t, id="w")
ggplot(t.m, aes(w, value)) + facet_wrap(~ variable) + geom_line()
于 2011-10-17T16:58:35.143 に答える