2014-06-12 16 views
15

Tôi có một DataFrame tìm kiếm như thế này:Pandas: Bar-Lô với hai quán bar và hai trục y

 amount  price 
age 
A  40929 4066443 
B  93904 9611272 
C 188349 19360005 
D 248438 24335536 
E 205622 18888604 
F 140173 12580900 
G  76243 6751731 
H  36859 3418329 
I  29304 2758928 
J  39768 3201269 
K  30350 2867059 

Bây giờ tôi muốn vẽ một thanh-cốt truyện với tuổi trên trục x dưới dạng nhãn. Đối với mỗi x-tick có hai thanh, một thanh cho số tiền, và một cho giá. Tôi có thể làm việc này bằng cách sử dụng đơn giản:

df.plot(kind='bar') 

Sự cố là mở rộng quy mô. Giá rất cao hơn nhiều mà tôi có thể không thực sự xác định số tiền trong đồ thị, xem:

enter image description here

Vì vậy, tôi muốn một trục y thứ hai. Tôi đã thử nó sử dụng:

df.loc[:,'amount'].plot(kind='bar') 
df.loc[:,'price'].plot(kind='bar',secondary_y=True) 

nhưng điều này chỉ ghi đè các quán bar và KHÔNG đặt chúng side-by-side. Có cách nào để làm điều này mà không cần phải truy cập matplotlib cấp thấp hơn (điều này có thể xảy ra rõ ràng bằng cách đặt các thanh song song bằng tay) không?

Còn bây giờ, tôi đang sử dụng hai lô duy nhất trong subplots:

df.plot(kind='bar',grid=True,subplots=True,sharex=True); 

kết quả là:

enter image description here

Trả lời

35

Sử dụng phiên bản gấu trúc mới (0.14.0 hoặc mới hơn) dưới đây mã sẽ hoạt động. Để tạo ra hai trục tôi đã tự tạo hai đối tượng trục matplotlib (axax2) sẽ phục vụ cho cả hai ô bar.

Khi vẽ một khung dữ liệu, bạn có thể chọn đối tượng trục sử dụng ax=.... Ngoài ra để ngăn không cho hai ô chồng lên nhau, tôi đã sửa đổi nơi chúng phù hợp với đối số từ khóa position, mặc định là 0.5 nhưng điều đó có nghĩa là hai ô thanh trùng nhau.

import matplotlib.pyplot as plt 
import numpy as np 
import pandas as pd 
from io import StringIO 

s = StringIO("""  amount  price 
A  40929 4066443 
B  93904 9611272 
C 188349 19360005 
D 248438 24335536 
E 205622 18888604 
F 140173 12580900 
G  76243 6751731 
H  36859 3418329 
I  29304 2758928 
J  39768 3201269 
K  30350 2867059""") 

df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True) 

fig = plt.figure() # Create matplotlib figure 

ax = fig.add_subplot(111) # Create matplotlib axes 
ax2 = ax.twinx() # Create another axes that shares the same x-axis as ax. 

width = 0.4 

df.amount.plot(kind='bar', color='red', ax=ax, width=width, position=1) 
df.price.plot(kind='bar', color='blue', ax=ax2, width=width, position=0) 

ax.set_ylabel('Amount') 
ax2.set_ylabel('Price') 

plt.show() 

Plot

+0

ah tốt đẹp, không biết về 'cái ax'-tham số. Thx – tim

+0

Điều này thật tuyệt! Nhưng ... nếu tôi thay đổi một trong các giá trị thành âm, thì kết quả sẽ bị ngắt. Bất kỳ ý tưởng làm thế nào để sửa chữa nó? – Dror

+0

Điều này thật tuyệt. Nhưng truyền thuyết chỉ xuất hiện cho màu xanh và không phải cả hai. –

6

Dưới đây là một phương pháp khác:

  • tạo tất cả các quán bar ở bên trái trục
  • di chuyển một số quán bar với các trục ngay bởi sự thay đổi đó là transform thuộc tính

Đây là mã:

import pylab as pl 
df = pd.DataFrame(np.random.rand(10, 2), columns=["left", "right"]) 
df["left"] *= 100 

ax = df.plot(kind="bar") 
ax2 = ax.twinx() 
for r in ax.patches[len(df):]: 
    r.set_transform(ax2.transData) 
ax2.set_ylim(0, 2); 

đây là kết quả:

enter image description here

+0

đẹp nhất là tốt, nhờ gợi ý về ax.patches :-) – tim

+0

và nếu bạn muốn các giá trị 'left' được chia tỷ lệ, bạn nên sử dụng' ax.patches [: len (df)] '. Chỉ cần nói ':). Câu trả lời tuyệt vời và súc tích! –

Các vấn đề liên quan