首页 > 解决方案 > R - ggplot2 - ggplot(data, aes(x=variable...)) 和 ggplot(data, aes(x=data$variable...)) 之间的区别

问题描述

我目前在ggplot2中遇到了一个现象,如果有人能给我一个解释,我将不胜感激。

我需要在直方图上绘制一个连续变量,并且需要在图上表示两个分类变量。以下数据框就是一个很好的例子。

library(ggplot2)


species <- rep(c('cat', 'dog'), 30)
numb <- rep(c(1,2,3,7,8,10), 10)
groups <- rep(c('A', 'A', 'B', 'B'), 15)

data <- data.frame(species=species, numb=numb, groups=groups)

让下面的代码表示一个连续变量的分类。

data$factnumb <- as.factor(data$numb)

如果我想绘制这个数据集,以下两个代码是完全可以互换的:

注意fill=语句后的区别。

p <- ggplot(data, aes(x=factnumb, fill=species)) +
        facet_grid(groups ~ .) +
        geom_bar(aes(y=(..count..)/sum(..count..))) +
        scale_y_continuous(labels = scales::percent)

情节(p): 在此处输入图像描述

q <- ggplot(data, aes(x=factnumb, fill=data$species)) +
        facet_grid(groups ~ .) +
        geom_bar(aes(y=(..count..)/sum(..count..))) +
        scale_y_continuous(labels = scales::percent)

情节(q): 在此处输入图像描述

但是,当使用现实生活中的连续变量时,并非所有类别都包含观察值,我仍然需要在 x 轴上表示空类别,以便获得样本分布的近似值。为了演示这一点,我使用了以下代码:

data_miss  <- data[which(data$numb!= 3),]

这导致分类变量的水平与数据集中的观察值之间存在差异:

> unique(data_miss$factnumb)
[1] 1  2  7  8  10
Levels: 1 2 3 7 8 10

并绘制了data_miss数据集,仍然包括factnumb变量的所有级别。

pm <- ggplot(data_miss, aes(x=factnumb, fill=species)) +
        facet_grid(groups ~ .) +
        geom_bar(aes(y=(..count..)/sum(..count..))) +
        scale_fill_discrete(drop=FALSE) +
        scale_x_discrete(drop=FALSE)+
        scale_y_continuous(labels = scales::percent)

情节(下午): 在此处输入图像描述

qm <- ggplot(data_miss, aes(x=factnumb, fill=data_miss$species)) +
        facet_grid(groups ~ .) +
        geom_bar(aes(y=(..count..)/sum(..count..))) +
        scale_x_discrete(drop=FALSE)+
        scale_fill_discrete(drop=FALSE) +
        scale_y_continuous(labels = scales::percent)

情节(平方米): 在此处输入图像描述

在这种情况下,当使用fill=data_miss$species时,绘图的填充会发生变化(并且变得更糟)。

如果有人能帮我解决这个问题,我会非常高兴。

只是“运气”,在情节 1 和 2 的情况下填充是相同的,还是我在 ggplot2 的精细机械中偶然发现了一些微妙的错误?

提前致谢!

亲切的问候,

贝尔纳黛特

标签: rplotggplot2

解决方案


在里面使用aes(data$variable)从来都不好,从不推荐,也不应该使用。有时它仍然有效,但aes(variable) 始终有效,因此您应该始终使用aes(variable).

更多解释:

ggplot使用非标准评估标准评估R 函数只能看到全局环境中的对象。如果我有以mydata列名命名的数据col1,并且我这样做mean(col1)了,我会收到一个错误:

mydata = data.frame(col1 = 1:3)
mean(col1)
# Error in mean(col1) : object 'col1' not found

发生此错误是因为col1不在全局环境中。mydata它只是数据框的列名。

aes函数在幕后做了额外的工作data,除了检查全局环境外,还知道查看图层的列。

ggplot(mydata, aes(x = col1)) + geom_bar()
# no error

不过,您不必在里面使用一列aes。为了提供灵活性,您可以执行列的功能,甚至是您碰巧在现场定义的其他向量(如果它具有正确的长度):

# these work fine too
ggplot(mydata, aes(x = log(col1))) + geom_bar()
ggplot(mydata, aes(x = c(1, 8, 11)) + geom_bar()

col1那么和 和有什么区别mydata$col1呢?嗯,col1是一个列的名称,并且mydata$col1是实际值。ggplot将在您的数据中查找名为 的列col1,并使用它。mydata$col1只是一个向量,它是完整的列。差异很重要,因为ggplot经常进行数据操作。每当有方面或聚合函数时,ggplot 就会将您的数据分成几部分并做一些事情。为了有效地做到这一点,它需要知道识别数据和列名。当你给它时mydata$col1,你并没有给它一个列名,你只是给它一个值向量 - 无论该列中发生什么,事情都不起作用。

aes()因此,只需在without中使用不带引号的列名,data$一切都会按预期工作。


推荐阅读