为什么ggplot2以不同的方式查看data.frame和data_frame?

时间:2017-10-10 15:13:17

标签: r ggplot2 dplyr

我有两个非常相似的数据框,ggplot2看到的不同;虽然内容相同,但数据结构略有不同。一个是data.frame,另一个是data_frame。我想了解ggplot2如何看待它们的区别。在以下示例中,两者都在stat_function中使用;当data.frame产生错误时,data_frame会生成图表。考虑到Hadleyverse中软件包的互操作性,这尤其令人困惑。当我发现我无法从dplyr生成的数据框(dplyr将data.frames转换为data_frames)创建绘图时,我首先遇到了这个问题,而我认为数据框是相同的(它不是,它是一个data.frame)工作正常。

示例1

首先,来自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

现在来自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

示例2

此示例生成不同的错误消息,但可能底层问题相同。首先,工作版本为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

这是带有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

1 个答案:

答案 0 :(得分:2)

ggplot看到了一个预期值的数据框。

这是由应用于data.frametibble(Hadley的dplyr首选的数据框)时应用的子集化方括号运算符返回的数据类型之间的差异造成的。设置data.frame可以默认更改类型,例如返回向量或值。对tibble进行子集将返回tibble,除非用户明确请求重新投射,例如使用pull或双括号[[]]。错误消息“数学函数的非数字参数”应该是一个线索。

以下代码通过适当地重新构建tibble来演示这一点。 库(GGPLOT2) 库(dplyr)

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

子集tibble(又名tbl_df)会返回tbl_df

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

可以使用双方括号[[]]pull重新制作。

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

子集data.frame会返回一个数字向量。

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

使用参数tibble可以生成对drop=FALSE进行子集化的行为,即无重新转换。

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

最后,显示解决类型问题可以解决绘图问题......

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])))

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 created when types are correct