2016-06-22 3 views
0

J'ai un grand cadre de données que je voudrais convertir en données de forme large en utilisant la fonction dcast() dans le paquet reshape2. Toutefois, la colonne de valeur est une colonne de caractères, mais certaines de ses valeurs sont des valeurs numériques au format de chaîne. J'ai essayé de créer une fonction d'agrégat personnalisée pour traiter cela, qui retournera la moyenne s'il y a des entrées numériques, mais retournera la première entrée si toutes les entrées sont non numériques. Bien que la fonction semble fonctionner, elle renvoie une erreur lorsqu'elle est utilisée comme fun.agrgregate. Ci-dessous est le code avec un exemple de jouet plus petit à démontrer. Ce que je veux, c'est une trame de données 3x5 avec la première colonne la variable de regroupement, 3 colonnes de valeurs numériques, et 1 colonne de valeurs de caractères.Comment créer une fonction d'agrégat personnalisée pour dcast qui peut gérer à la fois les caractères et l'entrée numérique?

mean_with_char <- function(x) { 
xnum <- as.numeric(x) 
if (any(!is.na(xnum))) mean(xnum, na.rm=TRUE) else x[1] 
} 

library(reshape2) 

fakedata <- data.frame(grp1 = rep(letters[1:3],times=20), grp2 = rep(LETTERS[17:20],each=15), val=rnorm(60)) 
fakedata$val[46:60] <- rep(c('foo','bar','bla','bla','bla','bla'), length.out=15) 

# This returns a 3x5 data frame with NA entries. 
dcast(fakedata, grp1 ~ grp2, value.var='val', fun.aggregate=mean) 

# This returns an error. 
dcast(fakedata, grp1 ~ grp2, value.var='val', fun.aggregate=mean_with_char) 

erreur dans vapply (indices, fun, .default): les valeurs doivent être de type 'caractère', mais FUN (X [[1]]) résultat est de type 'double'

+1

Il semble que 'vapply' veut que tous les résultats soient d'un type variable au lieu d'un mélange. Un travail autour serait de faire vos chiffres (les moyens) caractères, puis convertir les types après. J'ai utilisé 'readr :: type_convert' pour ce genre de chose. – aosmith

Répondre

0

Voici la solution de contournement proposée par aosmith. La fonction mean_with_char renvoie uniquement la sortie de caractères et la fonction numstring2num convertit les chaînes numériques en valeurs numériques.

mean_with_char <- function(x) { 
    xnum <- as.numeric(x) 
    if (any(!is.na(xnum))) as.character(mean(xnum, na.rm=TRUE)) else x[1] 
} 

library(reshape2) 

fakedata <- data.frame(grp1 = rep(letters[1:3],times=20), grp2 = rep(LETTERS[17:20],each=15), val=rnorm(60)) 
fakedata$val[46:60] <- rep(c('foo','bar','bla','bla','bla','bla'), length.out=15) 

fakecast <- dcast(fakedata, grp1 ~ grp2, value.var='val', fun.aggregate=mean_with_char) 

# Function to change columns in a df that only consist of numeric strings to numerics. 
numstring2num <- function(x) { 
    xnum <- as.numeric(x) 
    if (!any(is.na(xnum)) & !is.factor(x)) xnum else x 
} 


fakecast[] <- lapply(fakecast[], numstring2num)