web-dev-qa-db-fra.com

Nuage de points avec barres d'erreur

Comment puis-je générer le tracé suivant dans R? Les points indiqués dans le graphique sont les moyennes et leurs plages correspondent aux valeurs minimales et maximales. J'ai des données dans deux fichiers (ci-dessous est un exemple).

x   y
1   0.8773
1   0.8722
1   0.8816
1   0.8834
1   0.8759
1   0.8890
1   0.8727
2   0.9047
2   0.9062
2   0.8998
2   0.9044
2   0.8960
..  ...

enter image description here

44
sherlock85

Tout d'abord: il est très regrettable et surprenant que R ne puisse pas tracer de barres d'erreur "prêtes à l'emploi" .

Voici ma solution préférée, l’avantage est que vous n’avez pas besoin de paquets supplémentaires. L'astuce consiste à dessiner des flèches (!) Mais avec de petites barres horizontales au lieu de pointes de flèches (!!!). Cette idée pas si simple vient de R Wiki Tips et est reproduite ici à titre d'exemple élaboré.

Supposons que vous avez un vecteur de "valeurs moyennes" avg et un autre vecteur de "écarts types" sdev, ils ont la même longueur que n. Faisons en abscisse le nombre de ces "mesures", donc x <- 1:n. En utilisant celles-ci, voici les commandes de traçage:

plot(x, avg,
    ylim=range(c(avg-sdev, avg+sdev)),
    pch=19, xlab="Measurements", ylab="Mean +/- SD",
    main="Scatter plot with std.dev error bars"
)
# hack: we draw arrows but with very special "arrowheads"
arrows(x, avg-sdev, x, avg+sdev, length=0.05, angle=90, code=3)

Le résultat ressemble à ceci:

example scatter plot with std.dev error bars

Dans la arrows(...) la fonction length=0.05 Est la taille de la "tête de flèche" en pouces, angle=90 Spécifie que la "tête de flèche" est perpendiculaire à la flèche, et le Le paramètre code=3 particulièrement intuitif indique que nous voulons dessiner une flèche aux deux extrémités de la flèche.

Pour les barres d'erreur horizontales, les modifications suivantes sont nécessaires, en supposant que le vecteur sdev contienne maintenant les erreurs dans les valeurs x et que les valeurs y soient les ordonnées:

plot(x, y,
    xlim=range(c(x-sdev, x+sdev)),
    pch=19,...)
# horizontal error bars
arrows(x-sdev, y, x+sdev, y, length=0.05, angle=90, code=3)
113
Laryx Decidua

Utiliser ggplot et un peu dplyr pour la manipulation de données:

set.seed(42)
df <- data.frame(x = rep(1:10,each=5), y = rnorm(50))

library(ggplot2)
library(dplyr)

df.summary <- df %>% group_by(x) %>%
    summarize(ymin = min(y),
              ymax = max(y),
              ymean = mean(y))

ggplot(df.summary, aes(x = x, y = ymean)) +
    geom_point(size = 2) +
    geom_errorbar(aes(ymin = ymin, ymax = ymax))

S'il existe une colonne de regroupement supplémentaire (par exemple, le tracé de OP contient deux barres d'erreur par valeur x, indiquant que les données proviennent de deux fichiers), vous devez alors obtenir toutes les données dans un cadre de données au début, puis ajouter la variable de regroupement à l'élément dplyr::group_by Appelez (par exemple, group_by(x, file) si file est le nom de la colonne) et ajoutez-la en tant qu'esthétique de "groupe" dans le ggplot, par exemple, aes(x = x, y = ymean, group = file).

8
Gregor
#some example data
set.seed(42)
df <- data.frame(x = rep(1:10,each=5), y = rnorm(50))

#calculate mean, min and max for each x-value
library(plyr)
df2 <- ddply(df,.(x),function(df) c(mean=mean(df$y),min=min(df$y),max=max(df$y)))

#plot error bars
library(Hmisc)
with(df2,errbar(x,mean,max,min))
grid(nx=NA,ny=NULL)
6
Roland

Pour résumer la réponse de Laryx Decidua:

définir et utiliser une fonction comme celle-ci

plot.with.errorbars <- function(x, y, err, ylim=NULL, ...) {
  if (is.null(ylim))
    ylim <- c(min(y-err), max(y+err))
  plot(x, y, ylim=ylim, pch=19, ...)
  arrows(x, y-err, x, y+err, length=0.05, angle=90, code=3)
}

où l’on peut écraser l’automatique ylim, mais aussi passer des paramètres supplémentaires tels que principal, xlab, ylab.

3
Ehud Schreiber

Une autre façon (plus facile - du moins pour moi) de faire cela est la suivante.

install.packages("ggplot2movies")

data(movies, package="ggplot2movies")
rating_by_len = tapply(movies$length,
                       movies$rating,
                       mean)

plot(names(rating_by_len), rating_by_len, ylim=c(0, 200)
     ,xlab = "Rating", ylab = "Length", main="Average Rating by Movie Length", pch=21)
sds = tapply(movies$length, movies$rating, sd)
upper = rating_by_len + sds
lower = rating_by_len - sds
segments(x0=as.numeric(names(rating_by_len)), 
         y0=lower, 
         y1=upper)

J'espère que ça t'as aidé.

1
aggers