web-dev-qa-db-fra.com

Parcelles multiples utilisant des boucles en R

J'essaie encore de me faire une idée en utilisant des boucles pour tracer en R. Je voudrais tracer (tout tracé pour visualiser les données fera) les colonnes z_1 à z_2 dans le bloc de données ci-dessous en fonction des noms différents dans la colonne x_1.

x_1 <- c("A1", "A1","A1", "B10", "B10", "B10","B10", "C100", "C100", "C100")


z_1 <- rnorm(10, 70) 

z_2 <- rnorm(10, 1.7)

A <- data.frame(x_1, z_1, z_2)

En tant que tel, je voudrais me retrouver avec trois parcelles différentes; un pour la catégorie A1, un pour B10 et un autre pour C100. Je peux le faire en utilisant trois codes différents, mais j'aimerais pouvoir utiliser une boucle ou tout autre code unique pour exécuter les trois graphiques sur la même page. En réalité, j'ai un grand ensemble de données (4 000 lignes) et j'aimerais tracer deux identifiants sur une page (disons 5 sur une page). 

J'espère que cela a du sens. Merci de votre aide. 

Voici ma tentative de les tracer individuellement:

pour A1:

data_A1 <- A[which(A$x_1 == "A1"), ]
plot(data_A1$z_2, data_A1$z_1)

J'ai aussi essayé quelque chose comme ça mais j'ai des messages d'erreur

for ( i in A$x_1[[i]]){

plot(A[which(A$x_1==A$x_1[[i]]), ], aspect = 1)
}
13
John_dydx

Une approche simple avec des boucles serait

for (cat in unique(x_1)){
  d <- subset(A, x_1 == cat)
  plot(d$z_1, d$z_2)
}

unique(x_1) vous donne toutes les valeurs uniques de x_1. Ensuite, pour chacune de ces valeurs, obtenez un sous-ensemble correspondant et utilisez ce sous-ensemble pour le traçage.

14
Mark Heckmann

Juste pour comprendre pourquoi votre code original n'a pas fonctionné:

La configuration des données fonctionne bien

x_1 <- c("A1", "A1", "A1", "B10", "B10", "B10","B10", "C100", "C100", "C100")
z_1 <- rnorm(10, 70) 
z_2 <- rnorm(10, 1.7)
A <- data.frame(x_1, z_1, z_2)

L'intrigue individuelle fonctionne bien, mais comme je l'ai dit dans un commentaire, la variable which est inutile.

data_A1 <- A[which(A$x_1 == "A1"), ] # your way
plot(data_A1$z_2, data_A1$z_1)

data_A1 <- A[A$x_1 == "A1", ]    # deleting which() makes it cleaner
with(data_A1, plot(z_2, z_1))    # you can also use with() to save typing

Maintenant la boucle for. Passons en revue une simple boucle for en R (assez proche de l'exemple de ?"for"):

for (i in 1:5) {
   print(1:i)
}

Plutôt simple, 1:5 est c(1, 2, 3, 4, 5), donc i est d'abord 1, puis 2, etc. Votre boucle for a un problème dans cette première ligne:

for (i in A$x_1[[i]]) { ## already a problem

La première i est A$x_1[[i]]? Cela ne marchera pas, i n'est pas encore défini. De plus, A$x_1 est un vecteur, pas une liste, vous ne devriez donc pas utiliser [[ pour le sous-définir. Mais nous ne voulons pas encore de sous-ensemble, nous voulons un vecteur des valeurs que i devrait prendre. for (i in c("A1", "B10", "C100")) est ce que nous voulons dans ce cas, mais nous souhaitons également le faire par programme au lieu de saisir toutes les possibilités. Il y a plusieurs façons courantes d'obtenir cela:

unique(A$x_1) # as in Mark's solution
levels(A$x_1) # works because A$x_1 is a factor

Nous pouvons mettre l'une de ces expressions après la in. J'ai changé votre [[ en [ dans l'appel de tracé. [[ est pour les listes seulement. J'ai aussi sorti le which() inutile

for (i in unique(A$x_1)) {   # this line is good
    plot(A[A$x_1==A$x_1[i], ], aspect = 1)  # still a problem
}

Rappelons-nous les valeurs que i prend: "A1", "B10", "C100". Qu'est-ce que A$x_1 == A$x_1["A1"] va donner? Rien d'utile.

for (i in unique(A$x_1)) {  
    plot(A[A$x_1 == i, ], aspect = 1)  # getting there
}

Le code ci-dessus trace quelque chose, et c'est bien, mais ce n'est pas ce que vous voulez. Il y a toute une série d'avertissements, tous nous disant que aspect n'est pas un argument valable, nous allons donc le supprimer. En regardant le graphique, vous verrez qu'il représente 3 variables, parce que nous ne lui avons pas dit quoi mettre sur les axes x et y.

for (i in unique(A$x_1)) {   
    plot(A[A$x_1==i, "z_2"], A[A$x_1==i, "z_1"])  # z_2 on x, z_1 on y 
}   # Works!!!

Notez que ceci est presque identique à la réponse de Mark. Vous n'êtes pas obligé d'utiliser i et j dans les boucles for, il a utilisé cat. Il est recommandé d’utiliser un nom plus descriptif . Maintenant, imaginons-le un peu:

for (i in unique(A$x_1)) {   
    plot(A[A$x_1==i, "z_2"], A[A$x_1==i, "z_1"],
         xlim = range(A$z_2), ylim = range(A$z_1), # base the axes on full data range
         main = paste("Plot of", i))  # Give each a title
}

La prochaine fois: n'oubliez pas que vous pouvez exécuter de minuscules morceaux de code pour voir ce qu'ils sont. Si vous avez une ligne comme for (i in A$x_1[[i]]) dont vous n'êtes pas sûr, saisissez A$x_1[[i]] sur la console. Nous espérons que cela vous aidera à comprendre que vous n'avez pas défini i.

for (i in A$x_1)

ensuite, vous exécutez A$x_1 et réalisez que sa longueur est de 10. Vous voulez 3 graphes, pas 10, vous avez donc besoin de i pour prendre 3 valeurs, toutes différentes, etc.

13
Gregor

Peut-être que vous n'avez pas besoin d'une boucle. Essayez d'utiliser ggplots facet_grid () . Voici le documentation , plein d'exemples.

library(ggplot2)
library(reshape2)

melted_a <- melt(A)


ggplot(melted_a, aes(variable, value)) +
  geom_jitter() +
  facet_grid(. ~ x_1)

ggplot(melted_a, aes(variable, value)) +
  geom_jitter() +
  facet_grid(variable ~ x_1)

Edit Peut-être que cela résout ce problème. Mais si vous avez besoin de créer plusieurs parcelles ayant une structure similaire, vous pouvez créer une fonction et utiliser aes_string() au lieu de aes(). Note: Je ne suis pas un expert en écriture de fonctions, donc quelqu'un pourrait probablement l'éditer et l'améliorer. (pas testé)

ggplot_fun <- function(data, x, y, rowfacet, colfacet, ...){
  p <- ggplot(data, aes_string(x, y))
  p <- p + geom_jitter()
  p <- p + facet_grid(as.formula(sprintf("%s ~ %s", rowfacet, colfacet))
}

ggplot_fun(melted_a, variable, value, variable, x_1)

Idée tirée de cette question .

3
marbel

Vous pouvez également modifier les données, par exemple comme je l'ai fait ici ....

Si je veux des graphes datewise et xlab, ylab et le titre du complot pour avoir des détails spécifiques ...

 for ( i in 1:length(unique(wheeldata$Date)) ){
     d <- subset( wheeldata, Date == unique ( wheeldata$Date )[i] )
     plot(d$X, d$Y, xlab = "X", ylab = "Y", main = paste0("Date: ",  unique(d$Date)) )
 }
1
Manoj Kumar