自动绘制大小和固定宽度的条形图

时间:2019-05-03 21:29:03

标签: r ggplot2 width autosize gridextra

我遇到了麻烦,而且我不知道该怎么解释,所以请提前抱歉。

我有一个脚本,因为它很大,所以我不会在这里放它,所以让我们直接解决问题。

由于脚本生成的徽标是一种直方图,因此我将尝试通过示例来模拟问题。

我正在使用根据条形图的数量对直方图进行拆分的功能,最后,它生成了一个图,其中包含各种样点,每个样点都包含一个直方图。

myranges <- function(start, end, step){
  starts <- seq(start, end, step+1)
  ends <- pmin(starts + step, end)
  data.frame(a = starts, b = ends)
}

d <- data.frame(a = letters[1:10] , b = seq(1, 20, by =2 ))


num_bar_per_hist <- 2

p_list <- apply(
  myranges(1, nrow(d), num_bar_per_hist - 1),
  1,
  function(x){
    #as.matrix(d[x[1]:x[2]],)
    ggplot(d[x[1]:x[2] , ], aes(x=a, y=b)) + 
      geom_bar(stat = "identity") +
      ylim(0,22) +
      theme_classic()
  }
)
do.call(gridExtra::grid.arrange, c(p_list, ncol=2))

上面是生成绘图的脚本片段。
我更改了变量num_bar_per_hist以拆分直方图。 在这个例子中,我得到了这个:

enter image description here

如果将num_bar_per_hist的值更改为5,我得到:

enter image description here

这两个示例表明,每个图的宽度保持不变,条形图的宽度也保持不变。
但是,如果我将num_bar_per_hist更改为3,则会得到:

enter image description here

我想要的是将条形的宽度保持相同的大小。就是说,应将j条对齐,并使其与d条相同的宽度在右上方。

此外,如果可能的话,我不想更改脚本的结构(太多)或简单/小的更改。

我先谢谢了。 谢谢

编辑:

使用cowplot我可以解决部分问题。 (第3个图的相同参数)

num_bar_per_hist <- 3

p_list <- apply(
  myranges(1, nrow(d), num_bar_per_hist - 1),
  1,
  function(x){
    ggdraw() +
      draw_plot(
        ggplot(d[x[1]:x[2] , ], aes(x=a, y=b)) + 
          geom_bar(stat = "identity") +
          ylim(0, 22),
        width = (x[2] - x[1] + 1) / num_bar_per_hist
      )
  }
)
do.call(gridExtra::grid.arrange, c(p_list, ncol=2))

这样我就得到了:

enter image description here

这样,我就可以接近解决方案了。 j的宽度仍与其他宽度不同,但比第三个图好。
我仍然需要一些技巧或“魔术数”来改善条的宽度。由于采用了这种策略,最后一个小杂种比其他小种变得稀疏了。而且我只想使所有条形都具有相同的宽度,而与每个图具有的条形数量的差异无关。

1 个答案:

答案 0 :(得分:1)

您可以找出中断的数量,然后在其中修改每个图,以在x比例尺上添加虚拟中断,以确保它们都具有相同的中断,

import 'package:android_alarm_manager/android_alarm_manager.dart';


void runTimer()  async{
  await AndroidAlarmManager.periodic(const Duration(seconds: 2), 0, printHello, exact: true);
}

void printHello(){
  print("Hello");
}

main() async {
  await AndroidAlarmManager.initialize();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: Center(
          child: InkWell(onTap: runTimer,
              child: Container(child: Text('Run Timer'))),
        ),
      ),
    );
  }
}