web-dev-qa-db-fra.com

Boucle dans le cadre de données et les noms de variables

Je cherche un moyen d'automatiser certains diagrammes en R en utilisant une boucle FOR:

dflist <- c("dataframe1", "dataframe2", "dataframe3", "dataframe4")

for (i in dflist) {
  plot(i$var1, i$var2)
}

Toutes les images ont les mêmes variables, c’est-à-dire var1, var2. 

Il semble que les boucles for ne soient pas la solution la plus élégante, mais je ne comprends pas comment utiliser les fonctions apply pour les diagrammes.

MODIFIER:

Mon exemple initial utilisant mean() n'a pas aidé à la question initiale, alors je l'ai changé pour une fonction de tracé.

5
Timm S.

Pour ajouter quelque chose à la réponse de Beasterfield, il semble que vous souhaitiez effectuer un certain nombre d'opérations complexes sur chacun des blocs de données.

Il est possible d’avoir des fonctions complexes dans une instruction apply. Alors où vous avez maintenant:

for (i in dflist) {
  # Do some complex things
}

Cela peut être traduit en:

lapply(dflist, function(df) {
  # Do some complex operations on each data frame, df
  # More steps

  # Make sure the last thing is NULL. The last statement within the function will be
  # returned to lapply, which will try to combine these as a list across all data frames.
  # You don't actually care about this, you just want to run the function.
  NULL
})

Un exemple plus concret utilisant l'intrigue:

# Assuming we have a data frame with our points on the x, and y axes,
lapply(dflist, function(df) {
  x2 <- df$x^2
  log_y <- log(df$y)
  plot(x,y)
  NULL
})

Vous pouvez également écrire des fonctions complexes qui prennent plusieurs arguments:

lapply(dflist, function(df, arg1, arg2) {
  # Do something on each data.frame, df
  # arg1 == 1, arg2 == 2 (see next line)
}, 1, 2) # extra arguments are passed in here

J'espère que cela vous aide!

10
Scott Ritchie

En ce qui concerne votre question, vous devriez apprendre à accéder aux cellules, lignes et colonnes de data.frames, matrixs ou lists. À partir de votre code, je suppose que vous souhaitez accéder aux colonnes j 'e du fichier data.frame i, il devrait donc se lire:

mean( i[,j] )
# or
mean( i[[ j ]] )

L'opérateur $ ne peut être utilisé que si vous souhaitez accéder à une variable particulière dans votre data.frame, par exemple. i$var1. De plus, il est moins performant que d'accéder par [, ] ou [[]].

Cependant, bien que ce ne soit pas faux, l’utilisation de boucles for n’est pas très rish. Vous devriez en savoir plus sur les fonctions vectorisées et la famille apply. Donc, votre code pourrait être facilement réécrit en tant que:

set.seed(42)
dflist <- vector( "list", 5 )
for( i in 1:5 ){
  dflist[[i]] <- data.frame( A = rnorm(100), B = rnorm(100), C = rnorm(100) )
}
varlist <- c("A", "B")

lapply( dflist, function(x){ colMeans(x[varlist]) } )
6
Beasterfield

En prenant l'exemple de @Roland, je voulais vous montrer l'équivalent ggplot2. Nous devons d’abord changer un peu le datset:

D'abord les données d'origine:

> dflist
[[1]]
           x           y
1  0.9148060 -0.10612452
2  0.9370754  1.51152200
3  0.2861395 -0.09465904
4  0.8304476  2.01842371
5  0.6417455 -0.06271410
6  0.5190959  1.30486965
7  0.7365883  2.28664539
8  0.1346666 -1.38886070
9  0.6569923 -0.27878877
10 0.7050648 -0.13332134

[[2]]
            x          y
1   0.6359504 0.33342721
2  -0.2842529 0.34674825
3  -2.6564554 0.39848541
4  -2.4404669 0.78469278
5   1.3201133 0.03893649
6  -0.3066386 0.74879539
7  -1.7813084 0.67727683
8  -0.1719174 0.17126433
9   1.2146747 0.26108796
10  1.8951935 0.51441293

et mettre les données dans un data.frame, avec une colonne id

require(reshape2)
one_df = melt(dflist, id.vars = c("x","y"))
> one_df
            x           y L1
1   0.9148060 -0.10612452  1
2   0.9370754  1.51152200  1
3   0.2861395 -0.09465904  1
4   0.8304476  2.01842371  1
5   0.6417455 -0.06271410  1
6   0.5190959  1.30486965  1
7   0.7365883  2.28664539  1
8   0.1346666 -1.38886070  1
9   0.6569923 -0.27878877  1
10  0.7050648 -0.13332134  1
11  0.6359504  0.33342721  2
12 -0.2842529  0.34674825  2
13 -2.6564554  0.39848541  2
14 -2.4404669  0.78469278  2
15  1.3201133  0.03893649  2
16 -0.3066386  0.74879539  2
17 -1.7813084  0.67727683  2
18 -0.1719174  0.17126433  2
19  1.2146747  0.26108796  2
20  1.8951935  0.51441293  2

et faire l'intrigue:

require(ggplot2)
ggplot(one_df, aes(x = x, y = y)) + geom_point() + facet_wrap(~ L1)

enter image description here

2
Paul Hiemstra
set.seed(42)
dflist <- list(data.frame(x=runif(10),y=rnorm(10)),
               data.frame(x=rnorm(10),y=runif(10)))

par(mfrow=c(1,2))
for (i in dflist) {
  plot(y~x, data=i)
}
1
Roland

Basé sur la solution de Scott Ritchi, cet exemple serait reproductible, masquant également le message de retour de lapply:

# split dataframe by condition on cars hp
f <- function() trunc(signif(mtcars$hp, 2) / 100)
dflist <- lapply(unique(f()), function(x) subset(mtcars, f() == x ))

Cela divise la trame de données mtcars est un sous-ensemble basé sur la classification de variable hp (0 pour hp inférieur à 100, 1 pour ceux dans les 100, 2 pour 200, etc.)

Et, l'intrigue:

# use invisible to prevent the feedback message from lapply
invisible(
    lapply(dflist, function(df) {
    x2 <- df$mpg^2
    log_y <- log(df$hp)
    plot(x2, log_y)
    NULL
}))

invisible() empêchera le message lapply():

16 
9 
6 
1 
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

 enter image description here

0
f0nzie