将图的高度设置为在rmarkDown中的数据行数量等于相邻的表高度通过功能

发布于 2025-02-05 08:34:21 字数 1258 浏览 1 评论 0原文

我正在使用MTCARS数据在RmarkDown中的附带图和表创建。

---
title: "document"
author: "Maral Dorri"
date: 'May 2022'
output:
  html_document
---

我创建一个列并在右侧添加表:

<div class = "row">
<div class = "col-md-3">
```{r}
raw_dat <- mtcars[1:15, ] %>% rownames_to_column(var = "id") %>% select(id, mpg) %>% 
  mutate(links = paste(.$id, "And <a href = 'https://www.cars.com//'>here</a>"))
tibble(
  name = raw_dat$id,
  link = paste(raw_dat$mpg, "And <a href = 'https://www.cars.com//'>here</a>")) %>%
  mutate(link = map(link, gt::html)) %>%
  gt

```
</div>

然后我创建另一列并在左侧打印绘图。

<div class = "col-md-9">
```{r, fig.height=5.5}
   ggplot(raw_dat, aes(factor(id, rev(id)), mpg)) +
   geom_point() +
   coord_flip() +
   theme(plot.margin = margin(0.6, unit = "cm"))
```
</div>
</div>

结果为:

“在此处输入映像”

我知道我可以手动设置图形的高度大小与右侧的表相同,但是我想自动制作此功能,因为对于我的实际数据,它将定期更改。因此,用于图的高度的功能应根据表中的数据行数来进行。

所需的输出将在右侧的表中的每一行与左侧图的Y轴标签对齐,如图所示(手动完成,不是完美对齐)

I am using the mtcars data to create a side by side plot and table in Rmarkdown.

---
title: "document"
author: "Maral Dorri"
date: 'May 2022'
output:
  html_document
---

I create a column and add the table on the right:

<div class = "row">
<div class = "col-md-3">
```{r}
raw_dat <- mtcars[1:15, ] %>% rownames_to_column(var = "id") %>% select(id, mpg) %>% 
  mutate(links = paste(.$id, "And <a href = 'https://www.cars.com//'>here</a>"))
tibble(
  name = raw_dat$id,
  link = paste(raw_dat$mpg, "And <a href = 'https://www.cars.com//'>here</a>")) %>%
  mutate(link = map(link, gt::html)) %>%
  gt

```
</div>

Then I create another column and print the plot on the left

<div class = "col-md-9">
```{r, fig.height=5.5}
   ggplot(raw_dat, aes(factor(id, rev(id)), mpg)) +
   geom_point() +
   coord_flip() +
   theme(plot.margin = margin(0.6, unit = "cm"))
```
</div>
</div>

The results are:

enter image description here

I know I can set the height of the figure manually and capture the same size as the table on the right, but I want to make this automatic since for my actual data, it will be changing periodically. So the function used for the height of the plot should be in terms of number of rows of data in the table.

The desired output would line up each row of the data in the table on the right with the y axis labels of the plot on the left, as shown (done manually, and not perfectly aligned)

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

や莫失莫忘 2025-02-12 08:34:22

更新...

好吧,这将起作用,直到绘图扩展到绘图边距超过表的标头行高(约15行)的程度,

这就是样式和JS。

<style>
.main-container {
  max-width: unset;
}
</style>


```{r listen,results="asis",engine="js"}
// tbl font size is 1em (assuming-- rendered 16px; the padding t/b 8px)
// do what you're told 
setTimeout(function(){  // add to buttons
  ch = document.querySelector('.col-md-3').clientHeight; // how tall is the table
  sh = document.querySelector('.col-md-9');              // pull the 2nd column for manipulation
  si = document.querySelector('img');                    // assuming there's only one plot
  sih = si.clientHeight;                                 // plot height
  siw = si.clientWidth;                                  // plot width
  fs = $('.gt_table').css('line-height');                // size of text 
  bbt = $('.gt_table_body').css('border-top-width');     // table, head, body border (* 6)
  fss = parseInt(fs, 10);                                // strip the px from the value
  bbw = parseInt(bbt, 10);                               // strip the px from the value
  cz = sih/(sih - 11 - bbw - fss); // height of plot - margins - padding - the bottom (ticks, label, values)
  cha = ch * cz;                   // add additional height, was 1.075 before cz
  nw = siw/sih * cha;              // new width of plot
  sh.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;'); // shape container for centering
  si.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;');
  
  mm = document.querySelector('div.main-container > div.row'); // now get and set sizes for centering it all
  mc = mm.clientWidth;                                  // row width
  co = document.querySelector('.col-md-3').clientWidth; //  width of the table
  ms = (mc - nw - co)/2;                                // calc margin sizes
  mm.setAttribute('style', 'margin-left: ' + ms + 'px; margin-right: ' + ms + 'px;'); // center the content
}, 100) // you know, in case I'm slow...

```

这就是我的RMD中的样子。

---
title: "Untitled"
author: "me"
date: '2022-06-08'
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = F)
library(tidyverse)
library(gt)
data(mtcars)
```

<style>
.main-container {
  max-width: unset;
}
</style>

<div class = "row">
<div class = "col-md-3">

```{r tblr}
raw_dat <- mtcars[1:15, ] %>% rownames_to_column(var = "id") %>% select(id, mpg) %>% 
  mutate(links = paste(.$id, "And <a href = 'https://www.cars.com//'>here</a>"))
tibble(
  name = raw_dat$id,
  link = paste(raw_dat$mpg, "And <a href = 'https://www.cars.com//'>here</a>")) %>%
  mutate(link = map(link, gt::html)) %>%
  gt

```

</div>

<div class = "col-md-9">

```{r pltr}
   ggplot(raw_dat, aes(factor(id, rev(id)), mpg)) +
   geom_point() +
   coord_flip() +
   theme(plot.margin = margin(0.6, unit = "cm"))
```

</div>
</div>


```{r listen,results="asis",engine="js"}
// tbl font size is 1em (assuming-- rendered 16px; the padding t/b 8px)
// do what you're told 
setTimeout(function(){  // add to buttons
  ch = document.querySelector('.col-md-3').clientHeight; // how tall is the table
  sh = document.querySelector('.col-md-9');              // pull the 2nd column for manipulation
  si = document.querySelector('img');                    // assuming there's only one plot
  sih = si.clientHeight;                                 // plot height
  siw = si.clientWidth;                                  // plot width
  fs = $('.gt_table').css('line-height');                // size of text 
  bbt = $('.gt_table_body').css('border-top-width');     // table, head, body border (* 6)
  fss = parseInt(fs, 10);                                // strip the px from the value
  bbw = parseInt(bbt, 10);                               // strip the px from the value
  cz = sih/(sih - 11 - bbw - fss); // height of plot - margins - padding - the bottom (ticks, label, values)
  cha = ch * cz;                   // add additional height, was 1.075 before cz
  nw = siw/sih * cha;              // new width of plot
  sh.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;'); // shape container for centering
  si.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;');
  
  mm = document.querySelector('div.main-container > div.row'); // now get and set sizes for centering it all
  mc = mm.clientWidth;                                  // row width
  co = document.querySelector('.col-md-3').clientWidth; //  width of the table
  ms = (mc - nw - co)/2;                                // calc margin sizes
  mm.setAttribute('style', 'margin-left: ' + ms + 'px; margin-right: ' + ms + 'px;'); // center the content
}, 100) // you know, in case I'm slow...

```

更新

我没有意识到您希望标签能够在情节和表之间对齐。对此很抱歉。此更新的JS将创建所需的效果。

```{r listenOrElse,results="asis",engine="js"}

// do what you're told
setTimeout(function(){  // add to buttons
  ch = document.querySelector('.col-md-3').clientHeight;
  sh = document.querySelector('.col-md-9');
  si = document.querySelector('img'); // assuming there's only one!
  sih = si.clientHeight;
  siw = si.clientWidth;
  cha = ch * 1.075;   // add additional height, to account for plot padding
  nw = siw/sih * cha; // new width of plot
  console.log(ch);
  sh.style.height = cha + 'px';
  si.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px; padding-top: 5px;');
}, 100) // you know, in case I'm slow...

```

最初写的,

如果您想要col-md-3col-md-9的确切高度,则可以使用JS 。

我要指出的第一件事是,主要容器的最大宽度是一个问题。我真的建议您要么不设置这一点,要么更改价值。我认为它设置为960 PX。您可以更改带有样式的主要容器最大宽度属性。

<style>
.main-container {
  max-width: 1200px;
}
</style>

确保列的高度相同:

```{r listenOrElse,results="asis",engine="js"}

// do what you're told
setTimeout(function(){  
  ch = document.querySelector('.col-md-3').clientHeight; // get table height
  sh = document.querySelector('.col-md-9');
  si = document.querySelector('img');                // assuming there's only one!
  sih = si.clientHeight;
  siw = si.clientWidth;
  nw = siw/sih * ch;             // new width of plot (maintain aspect-ratio)
  sh.style.height = ch + 'px';   // change height of container
                                 // change height and width of plot
  si.setAttribute('style', 'height: ' + ch + 'px; width: ' + nw + 'px');
}, 100) // you know, in case I'm slow...

```

”在此处输入图像说明”

Update... again

Alright this will work until the plot has expanded to the point where the plot margin has scaled beyond the height of the table's header row (about 15 rows)

This is the styles and JS.

<style>
.main-container {
  max-width: unset;
}
</style>


```{r listen,results="asis",engine="js"}
// tbl font size is 1em (assuming-- rendered 16px; the padding t/b 8px)
// do what you're told 
setTimeout(function(){  // add to buttons
  ch = document.querySelector('.col-md-3').clientHeight; // how tall is the table
  sh = document.querySelector('.col-md-9');              // pull the 2nd column for manipulation
  si = document.querySelector('img');                    // assuming there's only one plot
  sih = si.clientHeight;                                 // plot height
  siw = si.clientWidth;                                  // plot width
  fs = $('.gt_table').css('line-height');                // size of text 
  bbt = $('.gt_table_body').css('border-top-width');     // table, head, body border (* 6)
  fss = parseInt(fs, 10);                                // strip the px from the value
  bbw = parseInt(bbt, 10);                               // strip the px from the value
  cz = sih/(sih - 11 - bbw - fss); // height of plot - margins - padding - the bottom (ticks, label, values)
  cha = ch * cz;                   // add additional height, was 1.075 before cz
  nw = siw/sih * cha;              // new width of plot
  sh.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;'); // shape container for centering
  si.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;');
  
  mm = document.querySelector('div.main-container > div.row'); // now get and set sizes for centering it all
  mc = mm.clientWidth;                                  // row width
  co = document.querySelector('.col-md-3').clientWidth; //  width of the table
  ms = (mc - nw - co)/2;                                // calc margin sizes
  mm.setAttribute('style', 'margin-left: ' + ms + 'px; margin-right: ' + ms + 'px;'); // center the content
}, 100) // you know, in case I'm slow...

```

Here's how this is in my RMD altogether.

---
title: "Untitled"
author: "me"
date: '2022-06-08'
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = F)
library(tidyverse)
library(gt)
data(mtcars)
```

<style>
.main-container {
  max-width: unset;
}
</style>

<div class = "row">
<div class = "col-md-3">

```{r tblr}
raw_dat <- mtcars[1:15, ] %>% rownames_to_column(var = "id") %>% select(id, mpg) %>% 
  mutate(links = paste(.$id, "And <a href = 'https://www.cars.com//'>here</a>"))
tibble(
  name = raw_dat$id,
  link = paste(raw_dat$mpg, "And <a href = 'https://www.cars.com//'>here</a>")) %>%
  mutate(link = map(link, gt::html)) %>%
  gt

```

</div>

<div class = "col-md-9">

```{r pltr}
   ggplot(raw_dat, aes(factor(id, rev(id)), mpg)) +
   geom_point() +
   coord_flip() +
   theme(plot.margin = margin(0.6, unit = "cm"))
```

</div>
</div>


```{r listen,results="asis",engine="js"}
// tbl font size is 1em (assuming-- rendered 16px; the padding t/b 8px)
// do what you're told 
setTimeout(function(){  // add to buttons
  ch = document.querySelector('.col-md-3').clientHeight; // how tall is the table
  sh = document.querySelector('.col-md-9');              // pull the 2nd column for manipulation
  si = document.querySelector('img');                    // assuming there's only one plot
  sih = si.clientHeight;                                 // plot height
  siw = si.clientWidth;                                  // plot width
  fs = $('.gt_table').css('line-height');                // size of text 
  bbt = $('.gt_table_body').css('border-top-width');     // table, head, body border (* 6)
  fss = parseInt(fs, 10);                                // strip the px from the value
  bbw = parseInt(bbt, 10);                               // strip the px from the value
  cz = sih/(sih - 11 - bbw - fss); // height of plot - margins - padding - the bottom (ticks, label, values)
  cha = ch * cz;                   // add additional height, was 1.075 before cz
  nw = siw/sih * cha;              // new width of plot
  sh.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;'); // shape container for centering
  si.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px;');
  
  mm = document.querySelector('div.main-container > div.row'); // now get and set sizes for centering it all
  mc = mm.clientWidth;                                  // row width
  co = document.querySelector('.col-md-3').clientWidth; //  width of the table
  ms = (mc - nw - co)/2;                                // calc margin sizes
  mm.setAttribute('style', 'margin-left: ' + ms + 'px; margin-right: ' + ms + 'px;'); // center the content
}, 100) // you know, in case I'm slow...

```

Update

I didn't realize that you wanted the labels to align between the plot and the table. Sorry about that. This updated JS will create the desired effect.

```{r listenOrElse,results="asis",engine="js"}

// do what you're told
setTimeout(function(){  // add to buttons
  ch = document.querySelector('.col-md-3').clientHeight;
  sh = document.querySelector('.col-md-9');
  si = document.querySelector('img'); // assuming there's only one!
  sih = si.clientHeight;
  siw = si.clientWidth;
  cha = ch * 1.075;   // add additional height, to account for plot padding
  nw = siw/sih * cha; // new width of plot
  console.log(ch);
  sh.style.height = cha + 'px';
  si.setAttribute('style', 'height: ' + cha + 'px; width: ' + nw + 'px; padding-top: 5px;');
}, 100) // you know, in case I'm slow...

```

enter image description here

Originally wrote

If you want the exact height of col-md-3 and col-md-9 to be the same, you could use JS.

The first thing I'll point out is that the max-width of the main container is a problem. I really suggest that you either unset this or change the value. I think it's set to 960 px. You can change the main container max-width property with styles.

<style>
.main-container {
  max-width: 1200px;
}
</style>

Ensuring that the columns are the same height:

```{r listenOrElse,results="asis",engine="js"}

// do what you're told
setTimeout(function(){  
  ch = document.querySelector('.col-md-3').clientHeight; // get table height
  sh = document.querySelector('.col-md-9');
  si = document.querySelector('img');                // assuming there's only one!
  sih = si.clientHeight;
  siw = si.clientWidth;
  nw = siw/sih * ch;             // new width of plot (maintain aspect-ratio)
  sh.style.height = ch + 'px';   // change height of container
                                 // change height and width of plot
  si.setAttribute('style', 'height: ' + ch + 'px; width: ' + nw + 'px');
}, 100) // you know, in case I'm slow...

```

enter image description here

烛影斜 2025-02-12 08:34:22

bstfun软件包为此提供了一种不错的自动方法。 (请注意,软件包依赖于其他各种软件包,例如magickwebshot。)

library(patchwork)
# devtools::install_github("ddsjoberg/bstfun")
library(bstfun)
as_ggplot(my_table) + my_plot

如果可以近似,则可以使用表格和轴名为大致对齐:

as_ggplot(my_table) | (plot_spacer() / my_plot) +
  plot_layout(heights = c(1,90)) # manual adjustment
  

源数据

library(gt); library(tidyverse)
raw_dat <- mtcars[1:15, ] %>% rownames_to_column(var = "id") %>% select(id, mpg) %>% 
  mutate(links = paste(.$id, "And <a href = 'https://www.cars.com//'>here</a>"))
my_table <- tibble(
  name = raw_dat$id,
  link = paste(raw_dat$mpg, "And <a href = 'https://www.cars.com//'>here</a>")) %>%
  mutate(link = map(link, gt::html)) %>%
  gt

my_plot <- ggplot(raw_dat, aes(factor(id, rev(id)), mpg)) +
  geom_point() +
  coord_flip() +
  theme(plot.margin = margin(0.6, unit = "cm"))

The bstfun package offers a nice automatic approach for this. (Note the package relies on a variety of other packages, like magick and webshot.)

library(patchwork)
# devtools::install_github("ddsjoberg/bstfun")
library(bstfun)
as_ggplot(my_table) + my_plot

If it's ok to be approximate, you can get the table and axis names roughly aligned using:

as_ggplot(my_table) | (plot_spacer() / my_plot) +
  plot_layout(heights = c(1,90)) # manual adjustment
  

enter image description here

Source data

library(gt); library(tidyverse)
raw_dat <- mtcars[1:15, ] %>% rownames_to_column(var = "id") %>% select(id, mpg) %>% 
  mutate(links = paste(.$id, "And <a href = 'https://www.cars.com//'>here</a>"))
my_table <- tibble(
  name = raw_dat$id,
  link = paste(raw_dat$mpg, "And <a href = 'https://www.cars.com//'>here</a>")) %>%
  mutate(link = map(link, gt::html)) %>%
  gt

my_plot <- ggplot(raw_dat, aes(factor(id, rev(id)), mpg)) +
  geom_point() +
  coord_flip() +
  theme(plot.margin = margin(0.6, unit = "cm"))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文