草庐IT

关于 r:有没有办法操纵 ggplot 比例中断和标签?

codeneng 2023-03-28 原文

Is there a way of manipulating ggplot scale breaks and labels?

ggplot 通常可以很好地按比例创建合理的中断和标签。

但是,我发现在具有许多方面和可能是 formatter= 语句的情节中,标签往往会变得过于"密集"和叠印,例如在这张图片中:

1
2
3
4
5
6
7
8
9
df <- data.frame(
        fac=rep(LETTERS[1:10], 100),
        x=rnorm(1000)
)

ggplot(df, aes(x=x)) +
  geom_bar(binwidth=0.5) +
  facet_grid(~fac) +
  scale_x_continuous(formatter="percent")

我知道我可以通过向 scale_x_continuous.

提供 breaks=scale= 参数来明确指定刻度的中断和标签

但是,我正在处理包含许多问题和十几个交叉中断的调查数据,因此需要找到一种自动执行此操作的方法。

有没有办法告诉 ggplot 自动计算中断和标签,但只需要更少,比如在最小值、最大值和零点处?

编辑:理想情况下,我不想指定最小和最大点,而是以某种方式利用内置的 ggplot 刻度训练,并使用默认计算的刻度限制。


您可以在调用 ggplot 时传入诸如 min()max() 之类的参数来动态指定中断。听起来您将在各种数据中应用此方法,因此您可能需要考虑将其概括为一个函数并弄乱格式,但这种方法应该有效:

1
2
3
4
5
6
ggplot(df, aes(x=x)) +
  geom_bar(binwidth=0.5) +
  facet_grid(~fac) +
  scale_x_continuous(breaks = c(min(df$x), 0, max(df$x))
    , labels = c(paste( 100 * round(min(df$x),2),"%", sep =""), paste(0,"%", sep =""), paste( 100 * round(max(df$x),2),"%", sep =""))
    )

或使用 opts(axis.text.x = theme_text(angle = 90, hjust = 0)) 旋转 x 轴文本以产生类似:

更新

在最新版本的 ggplot2 中,scale_x_continuousbreakslabels 参数接受函数,因此可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
myBreaks <- function(x){
    breaks <- c(min(x),median(x),max(x))
    names(breaks) <- attr(breaks,"labels")
    breaks
}

ggplot(df, aes(x=x)) +
  geom_bar(binwidth=0.5) +
  facet_grid(~fac) +
  scale_x_continuous(breaks = myBreaks,labels = percent_format()) +
  opts(axis.text.x = theme_text(angle = 90, hjust = 1,size = 5))

  • @Chase 谢谢。是的,我考虑过这样做,但这并不理想。原因是数据可能是百分比、受访者人数、t-stat 分数或其他。计算最接近的幅度可能是一种选择,但我真正想做的是使用 ggplot 训练的比例,然后隐藏端点之间的标签。换句话说,有时我希望比例的上限为(例如)60%。我希望这是有道理的。
  • @Andrie - 明白了。所以你真正需要的是一个函数,它可以解释 x 轴上显示的数据类型(百分比、计数等)并相应地修改比例,对吧?您可以在列上使用 class() 来帮助告知这一点吗?或者其他一些数据/元数据可以告知您到底在绘制什么?假设您有一些信息来告知格式化的内容和方式,编写一个小函数来生成中断和标签的向量以传递给 scale_x_continuous() 应该不会太难。
  • @Chase我希望有人会提供更通用的方法。例如,在使用刻面和自由音阶时,例如facet_grid(~fac, scales="free"),每个方面的高断点和低断点通常是不同的。所以我真正想要的是在不指定中断的情况下抑制标签。
  • @Andrie 也许您可以提供一组更新的示例数据来更好地说明您的问题?据我所知,您至少有两个不同的问题。 1. 比例轴的过度绘制,2. 使用相同的代码块在不同的灯光下呈现相同的数据。您可以使用 ... + opts(axis.text.x = theme_text(angle = 90, hjust = 0)) 之类的东西来解决过度绘图问题。如果您想超越格式问题,我认为您将不得不编写自己的函数来将参数传递给 labels()breaks()
  • 1 用于建议更改文本的angular和文本的大小。这将有助于满足我的即时演示需求。
  • 1.5 接受。仅供参考,Hadley Wickham 在另一个论坛中回应说,目前我想做的事情并不容易,但在不久的将来版本中,人们将对中断和刻度线有更多的控制权。


scales 包包含几个 breaks_*label_* 函数,它们返回 ggplot 使用的函数(闭包)。因此,您可以为这些修改输出的package器编写一个package器。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
library(ggplot2)

# Compute the list of breaks using original_func,
# then remove any of these that occur in remove_list
remove_breaks <- function(original_func, remove_list = list()) {
  function(x) {
    original_result <- original_func(x)
    original_result[!(original_result %in% remove_list)]
  }
}

# Compute the list of labels using original_func,
# then remove any of these that occur in remove_list
remove_labels <- function(original_func, remove_list = list()) {
  function(x) {
    original_result <- original_func(x)
    replace(original_result, original_result %in% remove_list, '')
  }
}

# Original plot
ggplot(data.frame(x=c(1,2,3,4,5,6,7,8), y = c(1,4,9,16,25,36,49,64))) + geom_line(aes(x, y)) +
  scale_x_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = scales::label_number_auto()) +
  scale_y_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = scales::label_number_auto())

# Remove some breaks from the x-axis, and remove some labels from the y-axis
ggplot(data.frame(x=c(1,2,3,4,5,6,7,8), y = c(1,4,9,16,25,36,49,64))) + geom_line(aes(x, y)) +
  scale_x_continuous(breaks       = remove_breaks(scales::breaks_pretty(9), seq(3,6)),
                     minor_breaks = remove_breaks(scales::breaks_pretty(18), seq(3,6,0.5)),
                     labels       = scales::label_number_auto()) +
  scale_y_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = remove_labels(scales::label_number_auto(), seq(20, 30)))

当然,使用我简单的 remove_breaksremove_labels 函数,您仍然需要指定要删除的值,但是您可以轻松地将它们修改为删除最大值和最小值,删除指定范围内的任何值等

  • 在注意到问题的年龄有多大之前写了一个答案???。

有关关于 r:有没有办法操纵 ggplot 比例中断和标签?的更多相关文章

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  3. ruby - 在院子里用@param 标签警告 - 2

    我试图使用yard记录一些Ruby代码,尽管我所做的正是所描述的here或here#@param[Integer]thenumberoftrials(>=0)#@param[Float]successprobabilityineachtrialdefinitialize(n,p)#initialize...end虽然我仍然得到这个奇怪的错误@paramtaghasunknownparametername:the@paramtaghasunknownparametername:success然后生成的html看起来很奇怪。我称yard为:$yarddoc-mmarkdown我做错了什么?

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. 没有类的 Ruby 方法? - 2

    大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow

  6. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  7. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  8. ruby - 没有类方法获取 Ruby 类名 - 2

    如何在Ruby中获取BasicObject实例的类名?例如,假设我有这个:classMyObjectSystem我怎样才能使这段代码成功?编辑:我发现Object的实例方法class被定义为returnrb_class_real(CLASS_OF(obj));。有什么方法可以从Ruby中使用它? 最佳答案 我花了一些时间研究irb并想出了这个:classBasicObjectdefclassklass=class这将为任何从BasicObject继承的对象提供一个#class您可以调用的方法。编辑评论中要求的进一步解释:假设你有对象

  9. css - 用 watir 检查标签类? - 2

    我有一个div,它根据表单是否正确提交而改变。我想知道是否可以检查类的特定元素?开始元素看起来像这样。如果输入不正确,添加错误类。 最佳答案 试试这个:browser.div(:id=>"myerrortest").class_name更多信息:http://watir.github.com/watir-webdriver/doc/Watir/HTMLElement.html#class_name-instance_method另一种选择是只查看具有您期望的类的div是否存在browser.div((:id=>"myerrortes

  10. ruby - 没有轨道的 ActiveRecord 时区 - 2

    我在非Rails项目中使用ActiveRecord。在Rails中,我可以这样做:config.time_zone='EasternTime(US&Canada)'config.active_record.default_timezone='EasternTime(US&Canada)'但如果我不使用rails,我该如何设置时区? 最佳答案 ActiveRecord::Base.default_timezone='EasternTime(US&Canada)' 关于ruby-没有轨道的A

随机推荐