2017-10-14 1 views
1

Je veux écrire une fonction qui prend une trame de données en entrée et pour chaque variable numérique dans la trame de données, la fonction renvoie à l'utilisateur la moyenne des variables, gamme médiane et interquartile sous la forme d'une liste.Écrire une fonction R qui passe une trame de données et retourne une liste

La trame de données est ci-dessous:

'data.frame': 271 obs. of 6 variables: 
$ sample.id: int 1 2 4 5 6 7 8 9 12 13 ... 
$ zip  : int 48504 48507 48504 48507 48505 48507 48507 48503 48507 48505 ... 
$ ward  : int 6 9 1 8 3 9 9 5 9 3 ... 
$ Pb1  : num 0.344 8.133 1.111 8.007 1.951 ... 
$ Pb2  : num 0.226 10.77 0.11 7.446 0.048 ... 
$ Pb3  : num 0.145 2.761 0.123 3.384 0.035 ... 

La sortie devrait ressembler à:

$Pb1 
    Mean Median  IQR 
10.76687 3.56400 7.75100 

$Pb2 
    Mean Median  IQR 
10.43467 1.40000 4.50100 

$Pb3 
    Mean Median  IQR 
3.701434 0.839000 2.429500 

Voici mon code:

df.numeric.summary <- function(data) { 
    for (i in 1:ncol(data)) { 
    if (is.numeric(data[[i]]) == TRUE) { 
     variable_mean <- mean(data[[i]]) 
     variable_median <- median(data[[i]]) 
     variable_IQR <- IQR(data[[i]]) 
     variable_data <- data.frame(Mean = variable_mean, Median = variable_median, IQR = variable_IQR) 
    } 
    } 
    return(variable_data) 
} 

Mon code de résultat que dans Pb3, je pense que je ne pouvais pas utiliser for déclaration, mais comment pourrais-je obtenir la valeur de trois variables? Aussi, comment retourner le résultat dans une liste?

+1

Je pense que vous devriez reconsidérer votre choix de réponses acceptées ici. La croissance d'une trame de données dans une boucle 'for' est l'une des opérations les moins efficaces de tout R. Elle ne devrait jamais être utilisée. –

Répondre

2

Bien qu'il existe de bien meilleures façons de faire ce genre de chose dans R (je vous suggère de regarder comment utiliser lapply, comme suggéré dans au moins une autre réponse et un commentaire), je vais me concentrer sur votre approche en boucle. Votre erreur est que vous recréerez variable_data à partir de zéro à chaque passage dans la boucle. Il est comme si vous êtes allé:

for (i in 1:3) { 
    x = i 
} 
return(x) # <-- This will return a 3 

La solution pourrait consister à définir variable_data avant la boucle for, et utiliser rbind pour y ajouter du contenu:

df.numeric.summary <- function(data) { 
    variable_data = data.frame(variable_mean = numeric(0), variable_median = numeric(0), variable_IQR = numeric(0)) 
    for (i in 1:ncol(data)) { 
    if (is.numeric(data[[i]]) == TRUE) { 
     variable_mean <- mean(data[[i]]) 
     variable_median <- median(data[[i]]) 
     variable_IQR <- IQR(data[[i]]) 
     variable_data <- rbind(variable_data, data.frame(Mean = variable_mean, Median = variable_median, IQR = variable_IQR)) 
    } 
    } 
    return(variable_data) 
} 

En ce qui concerne la conversion d'un dataframe à un liste, ceci est une question distincte et a déjà été répondu by this stackoverflow question. La réponse la plus populaire est:

xy.list <- split(xy.df, seq(nrow(xy.df))) 

xy.df est le nom de votre dataframe.

4

Il existe une variété de degrés auquel vous pouvez simplifier/déplier, mais que diriez-vous:

df.numeric.val <- function(col) { 
    return(c(mean=mean(col),median=median(col),IQR=IQR(col))) 
} 
df.numeric.summary <- function(data) { 
    numcols <- sapply(data,is.numeric) 
    vals <- lapply(data[numcols],df.numeric.val) 
    return(vals) 
} 
df.numeric.summary(mtcars)