2017-10-10 2 views
0

J'ai deux trames de données très similaires, que ggplot2 voit différemment; Bien que le contenu soit le même, les structures de données sont subtilement différentes. L'un est un data.frame, l'autre un data_frame. Je voudrais comprendre la différence dans la façon dont ggplot2 les voit. Dans les exemples suivants, les deux sont utilisés dans un stat_function; le data.frame génère des tracés tandis que data_frame génère des erreurs. Ceci est particulièrement déroutant à la lumière de l'interopérabilité des paquets dans le Hadleyverse. J'ai d'abord rencontré ce problème lorsque j'ai découvert que je n'arrivais pas à créer une intrigue à partir d'un cadre de données produit par dplyr (dplyr transforme data.frames en data_frames) alors qu'un cadre de données que je pensais identique (il ne l'était pas, data.frame) a très bien fonctionné.Pourquoi ggplot2 voit-il différemment un fichier data.frame et un fichier data_frame?

Exemple 1

D'abord, la version de travail du data.frame.

library(ggplot2) 
library(dplyr) 

d.f <- data.frame(mean = 0, sd = 1) 
d_f <- data_frame(mean = 0, sd = 1) 

ggplot(data.frame(x=-3:3), aes(x)) + 
    stat_function(fun = function (x) dnorm(x, mean = d.f[1,1], sd = d.f[1,2])) 

plot from data.frame

Et maintenant, la version non-travail du data_frame.

ggplot(data.frame(x=-3:3), aes(x)) + 
    stat_function(fun = function (x) dnorm(x, mean = d_f[1,1], sd = d_f[1,2])) 
## Warning message: 
## Computation failed in `stat_function()`: 
## Non-numeric argument to mathematical function 

enter image description here

Exemple 2

Cet exemple produit un message d'erreur différent mais peut-être la question sous-jacente est la même. Tout d'abord, la version de travail avec un data.frame.

logistic <- function (x) { 1/(1 + exp(-x)) } 

d.f <- data.frame(b0 = -9, b1 = 0.8) 
d_f <- data_frame(b0 = -9, b1 = 0.8) 

ggplot(data.frame(x=0:20), aes(x)) + 
    stat_function(fun = function (x) logistic(d.f[1,1] + d.f[1,2] * x)) 

plot produced from data.frame

Et voici la version non-travail avec un data_frame.

ggplot(data.frame(x=0:20), aes(x)) + 
    stat_function(fun = function (x) logistic(d_f[1,1] + d_f[1,2] * x)) 
## Error in eval(expr, envir, enclos) : object 'y' not found 
+3

Essayez 'pull (d_f [1,2])'. C'est encore une machine après sous-ensemble. Mais ggplot attend un vecteur qui se corrige 'pull'. Jetez un coup d'oeil [ici] (https://stackoverflow.com/questions/21618423/extract-a-dplyr-tbl-column-as-a-vector) – Jimbou

+3

Ce n'est pas ggplot. La vérité est que 'data_frame's ne sont pas **' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '. Hadley a décidé qu'il n'aimait pas le comportement par défaut de 'data.frame's et il a intentionnellement modifié le comportement de' data_frame's. Utilisateur méfiez-vous. – joran

+2

... vous pouvez créer la même erreur avec 'data.frame's en faisant' d.f [1,1, drop = FALSE] ', je pense. – joran

Répondre

1

ggplot voyait une trame de données où il attendait une valeur.

Cela résultait des différences entre les types de données renvoyés par l'opérateur de sous-ensembles de tranches de code appliqués lors de l'application à data.frame ou tibble (la trame de données préférée par dplyr de Hadley). La souscription d'un data.frame peut changer les types par défaut, par ex. renvoyer un vecteur ou une valeur. La souscription d'un tibble renverra un tibble à moins que l'utilisateur ne demande explicitement le redondage, par ex. en utilisant pull ou double-parenthèses [[]]. Le message d'erreur "Argument non numérique à la fonction mathématique" aurait dû être un indice.

Le code suivant illustre cela en refaisant de façon appropriée le tibble s. bibliothèque (de ggplot2) bibliothèque (dplyr)

d.f <- data.frame(mean = 0, sd = 1) 
d_f <- data_frame(mean = 0, sd = 1) 

un tibble de sous-ensembles (aka tbl_df) retourne un tbl_df.

class(d_f[1,1]) 
## [1] "tbl_df"  "tbl"  "data.frame" 

Ce qui peut être refondue avec double crochets droits [[]] ou pull.

class(d_f[[1,1]]) 
## [1] "numeric" 
class(pull(d_f[1,1])) 
## [1] "numeric" 

un data.frame retourne sous-ensembles de un vecteur numérique.

class(d.f[1,1]) 
## [1] "numeric" 

Le comportement d'un de sous-ensembles tibble, à savoir pas de re-moulage, peut être produit avec l'argument drop=FALSE.

class(d.f[1,1, drop=FALSE]) 
## [1] "data.frame" 

Enfin, montrant que la résolution du problème de type résout le problème traçante ...

ggplot(data.frame(x=-3:3), aes(x)) + 
    stat_function(fun = function (x) dnorm(x, mean = pull(d_f[1,1]), sd = pull(d_f[1,2]))) 

et

ggplot(data.frame(x=-3:3), aes(x)) + 
    stat_function(fun = function (x) dnorm(x, mean = d_f[[1,1]], sd = d_f[[1,2]])) 

les deux produisent le complot prévu. plot created when types are correct