выравнивание отдельных не-фасетных графиков в 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 
 Brian Diggs19 июл. 2013 г., 18:00
unit.pmax это функция отдельно отunit (хотя оба вgrid пакет). Есть лиgrid.unit.pmax доступно в питоне послеgrid=importr("grid")? Или делаетrpy сделать какой-то перевод в точки в именах функций, которые не связаны с диспетчеризацией метода S3?
 baptiste19 июл. 2013 г., 19:15
@BrianDiggs кажется, чтоgrid::unit.pmax станетgrid.unit_pmax
 baptiste20 июл. 2013 г., 01:56
мне кажется, что gA и gB 'поля шириныt были обновлены до новых значений wA и wB.
 lgautier31 авг. 2013 г., 02:52
@ user248237dfsf - segfaults не должно произойти. Вы сообщили об этом на трекере проблем для rpy2?
 user248237dfsf19 июл. 2013 г., 13:32
те, кто пометил это как дубликат, не понимают тонкости перевода кода из R в Rpy2. Да, иногда перевод прост, но иногдаСчетчик интуитивно понятен. Это вопрос rpy2. Не прямой вопрос ggplot2. Вы просто вмешиваетесь и блокируете процесс вопросов и ответов без уважительной причины.
 baptiste19 июл. 2013 г., 22:58
боюсь, я могут помощь; этот синтаксис rpy совершенно чужд мне.
 user248237dfsf20 июл. 2013 г., 02:03
@baptiste: но похоже ли этоwA а такжеwB были обновлены правильно?
 user248237dfsf20 июл. 2013 г., 01:49
@baptiste: отредактированный ответ, чтобы иметь команды .. Я думаю, что ям близко, но пропущено что-то маленькое - возможно, передать по значению по сравнению с проблемой ссылки Точно сказать не могу
 user248237dfsf19 июл. 2013 г., 20:15
@baptiste: вы правы, спасибо, но я все еще не уверен, как получить доступ кgrob объекты из rpy2, см. editsI '
 baptiste20 июл. 2013 г., 01:08
какие's вывод ваших последних команд?

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

Выравнивание двух графиков становится намного сложнее, когда задействованы грани. Я нене знаю, есть ли общее решение даже в R. Рассмотрим этот сценарий,

p1 
 baptiste21 июл. 2013 г., 21:06
я не уверен, что понял, что ты имеешь в виду, но в любом случае ты выигралне должно быть одного графика с 3 гранями в верхнем ряду и одним фасетом, который охватывает всю ширину в нижнем ряду. Вам нужно использовать два участка для этого.
 user248237dfsf21 июл. 2013 г., 20:57
Еще одно замечание: насколько распространен этот метод использования разных типов geom в разных подмножествах данных? это позволит вам создать сюжет, который я намеревался в оригинальном посте, используя комбинациюgeom_density а также ?geom_barstackoverflow.com/questions/7903972/...I»
 user248237dfsf21 июл. 2013 г., 04:12
вопрос о вашем примере: если вы удалили легенду дляamВы могли бы выровнять их в R?
 user248237dfsf21 июл. 2013 г., 04:11
Но люди постоянно создают сложные сетки графиков в R .. так, каков общий способ сделать это? Есть ли способ получить исходный график, который я сделал в посте, используя фасеты, все внутри фасетирования ggplot (с facet_wrap и facet_grid), чтобы вообще избежать отдельной сетки? Возможно, я просто нене знаю, передовые применения огранки

Непроверенный перевод ответа с использованиемgridExtragrid.arrange(), Левые стороны графиков (где метки для оси Y) не всегда могут быть выровнены, хотя.

from rpy2.robjects.packages import importr
gridextra = importr('gridExtra')
from rpy2.robjects.lib import ggplot2
_ggplot2 = ggplot2.ggplot2
def dollar(x, name): # should be included in rpy2.robjects, may be...
    return x[x.index(name)]

def g_legend(a_gplot):
    tmp = _ggplot2.ggplot_gtable(_ggplot2.ggplot_build(a_gplot))
    leg = [dollar(x, 'name')[0] for x in dollar(tmp, 'grobs')].index('guide-box')
    legend = dollar(tmp, 'grobs')[leg]
    return legend
legend1 = g_legend(p1)
legend2 = g_legend(p2)
nolegend = ggplot2.theme(**{'legend.position': 'none'})
gridexta.grid_arrange(p1 + nolegend, legend1, 
                      p2 + nolegend, legend2,
                      ncol=2, widths = FloatVector((5.0/6,1.0/6)))

Разделить легенды от сюжетов (см.ggplot отдельная легенда и сюжет), затем используйтеgrid.arrange

library(gridExtra)
g_legend 
 user248237dfsf19 июл. 2013 г., 16:40
спасибо но этоне совсем понятно, как перевести это на rpy2 и ямы хотели бы избежать определения новых чисто R-функций, поскольку это еще больше усложняет перевод

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