выравнивание отдельных не-фасетных графиков в ggplot2 с использованием Rpy2 в Python

Я объединяю два отдельных графика в макет сетки сgrid как предложено @lgautier в rpy2 с использованием python. Верхний график представляет собой плотность, а нижний - гистограмму:

iris = r('iris')
import pandas

# define layout
lt = grid.layout(2, 1)
vp = grid.viewport(layout = lt)
vp.push()

# first plot
vp_p = grid.viewport(**{'layout.pos.row': 1, 'layout.pos.col':1})
p1 = ggplot2.ggplot(iris) + \
    ggplot2.geom_density(aes_string(x="Sepal.Width",
                                    colour="Species")) + \
    ggplot2.facet_wrap(Formula("~ Species"))
p1.plot(vp = vp_p)

# second plot
mean_df = pandas.DataFrame({"Species": ["setosa", "virginica", "versicolor"],
                            "X": [10, 2, 30],
                            "Y": [5, 3, 4]})
mean_df = pandas.melt(mean_df, id_vars=["Species"])
r_mean_df = get_r_dataframe(mean_df)
p2 = ggplot2.ggplot(r_mean_df) + \
     ggplot2.geom_bar(aes_string(x="Species",
                                 y="value",
                                 group="variable",
                                 colour="variable"),
                      position=ggplot2.position_dodge(),
                      stat="identity")
vp_p = grid.viewport(**{'layout.pos.row': 2, 'layout.pos.col':1})
p2.plot(vp = vp_p)

то, что я получаю, близко к тому, что я хочу, но графики не совсем выровнены (показано стрелками, которые я добавил): I '

Мне бы хотелось, чтобы регионы сюжета (а не легенды) точно совпадали. Как это может быть достигнуто? разница здесь не так велика, но когда вы добавляете условия к гистограмме ниже или делаете из них гистограмму с точкамиposition_dodge различия могут стать очень большими, и графики не выровнены.

Стандартное решение ggplot не может быть легко переведено на rpy2:

arrange по-видимомуgrid_arrange в :gridExtra

>>> gridExtra = importr("gridExtra")
>>> gridExtra.grid_arrange

ggplotGrob недоступен изggplot2, но можно получить доступ следующим образом:

>>> ggplot2.ggplot2.ggplotGrob

Хотя я не знаю, как получить доступ:grid::unit.pmax

>>> grid.unit

>>> grid.unit("pmax")
Error in (function (x, units, data = NULL)  : 
argument "units" is missing, with no default
rpy2.rinterface.RRuntimeError: Error in (function (x, units, data = NULL)  : 
argument "units" is missing, with no default

так что'Не ясно, как перевести стандартное решение ggplot2 в rpy2.

редактировать: как отметили другиеgrid::unit.pmax являетсяgrid.unit_pmax, Я до сих пор нене знаю, как получить доступ в rpy2widths параметрgrob Объекты, хотя, что необходимо, чтобы установить ширину графиков, чтобы быть шириной более широкого графика. Я имею:

gA = ggplot2.ggplot2.ggplotGrob(p1)
gB = ggplot2.ggplot2.ggplotGrob(p2)

g = importr("grid")
print "gA: ", gA
maxWidth = g.unit_pmax(gA.widths[2:5], gB.widths[2:5])

gA.widths не правильный синтаксис.grob объектgA печатает как:

gA:  TableGrob (8 x 13) "layout": 17 grobs
    z         cells       name                                    grob
1   0 ( 1- 8, 1-13) background          rect[plot.background.rect.350]
2   1 ( 4- 4, 4- 4)    panel-1                gTree[panel-1.gTree.239]
3   2 ( 4- 4, 7- 7)    panel-2                gTree[panel-2.gTree.254]
4   3 ( 4- 4,10-10)    panel-3                gTree[panel-3.gTree.269]
5   4 ( 3- 3, 4- 4)  strip_t-1    absoluteGrob[strip.absoluteGrob.305]
6   5 ( 3- 3, 7- 7)  strip_t-2    absoluteGrob[strip.absoluteGrob.311]
7   6 ( 3- 3,10-10)  strip_t-3    absoluteGrob[strip.absoluteGrob.317]
8   7 ( 4- 4, 3- 3)   axis_l-1 absoluteGrob[axis-l-1.absoluteGrob.297]
9   8 ( 4- 4, 6- 6)   axis_l-2         zeroGrob[axis-l-2.zeroGrob.298]
10  9 ( 4- 4, 9- 9)   axis_l-3         zeroGrob[axis-l-3.zeroGrob.299]
11 10 ( 5- 5, 4- 4)   axis_b-1 absoluteGrob[axis-b-1.absoluteGrob.276]
12 11 ( 5- 5, 7- 7)   axis_b-2 absoluteGrob[axis-b-2.absoluteGrob.283]
13 12 ( 5- 5,10-10)   axis_b-3 absoluteGrob[axis-b-3.absoluteGrob.290]
14 13 ( 7- 7, 4-10)       xlab             text[axis.title.x.text.319]
15 14 ( 4- 4, 2- 2)       ylab             text[axis.title.y.text.321]
16 15 ( 4- 4,12-12)  guide-box                       gtable[guide-box]
17 16 ( 2- 2, 4-10)      title               text[plot.title.text.348]

обновление: достигнут некоторый прогресс в доступе к ширине, но все еще не удается перевести решение. Чтобы установить ширину гробов, у меня есть:

# get grobs
gA = ggplot2.ggplot2.ggplotGrob(p1)
gB = ggplot2.ggplot2.ggplotGrob(p2)
g = importr("grid")
# get max width
maxWidth = g.unit_pmax(gA.rx2("widths")[2:5][0], gB.rx2("widths")[2:5][0])
print gA.rx2("widths")[2:5]
wA = gA.rx2("widths")[2:5]
wB = gB.rx2("widths")[2:5]
print "before: ", wA[0]
wA[0] = robj.ListVector(maxWidth)
print "After: ", wA[0]
print "before: ", wB[0]
wB[0] = robj.ListVector(maxWidth)
print "after:", wB[0]
gridExtra.grid_arrange(gA, gB, ncol=1)

Это работает, но не работает. Вывод:

[[1]]
[1] 0.740361111111111cm

[[2]]
[1] 1null

[[3]]
[1] 0.127cm


before:  [1] 0.740361111111111cm

After:  [1] max(0.740361111111111cm, sum(1grobwidth, 0.15cm+0.1cm))

before:  [1] sum(1grobwidth, 0.15cm+0.1cm)

after: [1] max(0.740361111111111cm, sum(1grobwidth, 0.15cm+0.1cm))

update2: понял, как @baptiste указал, что было бы полезно показать чистую версию R того, что яЯ пытаюсь воспроизвести в rpy2. Вот's чистая версия R:

df 

Ответы на вопрос(3)

Ваш ответ на вопрос