Tôi đang kết hợp hai ô riêng biệt vào bố cục lưới với grid
như được gợi ý bởi @lgautier trong rpy2 bằng python. Cốt truyện đầu là một mật độ và và phía dưới một biểu đồ hình cột:căn chỉnh các ô phi khía cạnh riêng biệt trong ggplot2 bằng cách sử dụng Rpy2 trong 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)
những gì tôi nhận được là gần với những gì tôi muốn nhưng âm mưu không chính xác liên kết (thể hiện bởi các mũi tên mà tôi thêm vào):
Tôi muốn khu vực ô (không phải là truyền thuyết) khớp chính xác. Làm thế nào có thể đạt được? sự khác biệt ở đây không quá lớn nhưng khi bạn thêm điều kiện vào biểu đồ thanh bên dưới hoặc làm cho biểu đồ thanh được né tránh với position_dodge
sự khác biệt có thể trở nên rất lớn và các ô không được căn chỉnh.
Giải pháp ggplot tiêu chuẩn có thể không dễ dàng được dịch ra tiếng rpy2:
arrange
dường như là grid_arrange
trong gridExtra
:
>>> gridExtra = importr("gridExtra")
>>> gridExtra.grid_arrange
<SignatureTranslatedFunction - Python:0x430f518/R:0x396f678>
ggplotGrob
là không thể truy cập từ ggplot2
, nhưng có thể được truy cập như thế này:
>>> ggplot2.ggplot2.ggplotGrob
Mặc dù tôi không biết cách truy cập grid::unit.pmax
:
>>> grid.unit
<bound method type.unit of <class 'rpy2.robjects.lib.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
vì vậy không rõ cách dịch giải pháp ggplot2 chuẩn thành rpy2.
chỉnh sửa: như những người khác đã chỉ ra grid::unit.pmax
là . Tuy nhiên, tôi vẫn không biết cách truy cập vào rpy2 thông số widths
của các đối tượng grob
, điều này là cần thiết để đặt độ rộng của ô là giá trị của ô rộng hơn. Tôi có:
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
không đúng cú pháp. Các đối tượng grob
gA
in như:
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]
update: thực hiện một số tiến bộ về độ rộng truy cập, nhưng vẫn không thể dịch các giải pháp. Để đặt chiều rộng của grobs, tôi có:
# 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)
Nó chạy nhưng không hoạt động. Kết quả đầu ra là:
[[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: nhận ra là @baptiste chỉ ra rằng sẽ hữu ích khi hiển thị phiên bản R thuần túy của những gì tôi đang cố gắng tái tạo trong rpy2. Dưới đây là phiên bản R tinh khiết:
df <- data.frame(Species=c("setosa", "virginica", "versicolor"),X=c(1,2,3), Y=c(10,20,30))
p1 <- ggplot(iris) + geom_density(aes(x=Sepal.Width, colour=Species))
p2 <- ggplot(df) + geom_bar(aes(x=Species, y=X, colour=Species))
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
gA$widths[2:5] <- as.list(maxWidth)
gB$widths[2:5] <- as.list(maxWidth)
grid.arrange(gA, gB, ncol=1)
Tôi nghĩ rằng điều này trong tác phẩm chung của hai tấm với truyền thuyết rằng có những khía cạnh khác nhau trong ggplot2 và tôi muốn thực hiện điều này trong rpy2.
UPDATE3: gần như đã nhận nó để làm việc, bằng cách xây dựng một FloatVector
lên một yếu tố tại một thời điểm:
maxWidth = []
for x, y in zip(gA.rx2("widths")[2:5], gB.rx2("widths")[2:5]):
pmax = g.unit_pmax(x, y)
print "PMAX: ", pmax
val = pmax[1][0][0]
print "VAL->", val
maxWidth.append(val)
gA[gA.names.index("widths")][2:5] = robj.FloatVector(maxWidth)
gridExtra.grid_arrange(gA, gB, ncol=1)
tuy nhiên điều này tạo ra một bãi chứa segfault/lõi:
Error: VECTOR_ELT() can only be applied to a 'list', not a 'double'
*** longjmp causes uninitialized stack frame ***: python2.7 terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f83742e2817]
/lib/x86_64-linux-gnu/libc.so.6(+0x10a78d)[0x7f83742e278d]
/lib/x86_64-linux-gnu/libc.so.6(__longjmp_chk+0x33)[0x7f83742e26f3]
...
7f837591e000-7f8375925000 r--s 00000000 fc:00 1977264 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
7f8375926000-7f8375927000 rwxp 00000000 00:00 0
7f8375927000-7f8375929000 rw-p 00000000 00:00 0
7f8375929000-7f837592a000 r--p 00022000 fc:00 917959 /lib/x86_64-linux-gnu/ld-2.15.so
7f837592a000-7f837592c000 rw-p 00023000 fc:00 917959 /lib/x86_64-linux-gnu/ld-2.15.so
7ffff4b96000-7ffff4bd6000 rw-p 00000000 00:00 0 [stack]
7ffff4bff000-7ffff4c00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
Cập nhật: tiền thưởng đã kết thúc. Tôi đánh giá cao các câu trả lời nhận được, nhưng không phải câu trả lời sử dụng rpy2 và đây là một câu hỏi rpy2, vì vậy về mặt kỹ thuật các câu trả lời không phải là về chủ đề. Có một giải pháp R đơn giản cho vấn đề này (ngay cả khi không có giải pháp cho điều này nói chung như @ baptiste đã chỉ ra) và câu hỏi đơn giản là cách dịch nó thành rpy2
những người đã đánh dấu mục này là trùng lặp không đánh giá cao sự tinh tế của bản dịch mã từ R thành Rpy2. Có, đôi khi bản dịch rất dễ nhưng đôi khi nó phản trực giác. Đây là một câu hỏi rpy2. Không phải là một câu hỏi ggplot2 thẳng lên. Bạn chỉ đang can thiệp và chặn quá trình hỏi và trả lời mà không có lý do chính đáng. – user248237dfsf
'unit.pmax' là một hàm tách biệt với' đơn vị' (mặc dù cả hai đều nằm trong gói 'grid'). Có 'grid.unit.pmax' có sẵn trong python sau' grid = importr ("grid") '? Hoặc không 'rpy' làm một số dịch để dấu chấm trong tên chức năng mà không liên quan đến công văn phương pháp S3? –
@BrianDiggs có vẻ là 'grid :: unit.pmax' sẽ trở thành' grid.unit_pmax' – baptiste