Định dạng trục y dưới dạng phần trăm


114

Tôi có một cốt truyện hiện có được tạo với những con gấu trúc như thế này:

df['myvar'].plot(kind='bar')

Trục y được định dạng là float và tôi muốn thay đổi trục y thành tỷ lệ phần trăm. Tất cả các giải pháp tôi tìm thấy đều sử dụng cú pháp ax.xyz và tôi chỉ có thể đặt mã bên dưới dòng bên trên để tạo ra cốt truyện (tôi không thể thêm ax = ax vào dòng bên trên.)

Làm cách nào để định dạng trục y dưới dạng tỷ lệ phần trăm mà không thay đổi dòng ở trên?

Đây là giải pháp tôi đã tìm thấy nhưng yêu cầu tôi xác định lại cốt truyện :

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mtick

data = [8,12,15,17,18,18.5]
perc = np.linspace(0,100,len(data))

fig = plt.figure(1, (7,4))
ax = fig.add_subplot(1,1,1)

ax.plot(perc, data)

fmt = '%.0f%%' # Format you want the ticks, e.g. '40%'
xticks = mtick.FormatStrFormatter(fmt)
ax.xaxis.set_major_formatter(xticks)

plt.show()

Liên kết đến giải pháp trên: Pyplot: sử dụng tỷ lệ phần trăm trên trục x


Bạn có thể vui lòng thay đổi câu trả lời được chấp nhận của mình thành cách tiếp cận được triển khai nguyên bản trong matplotlib không? stackoverflow.com/a/36319915/1840471
Max Ghenis

Câu trả lời:


128

Đây là một vài tháng muộn, nhưng tôi đã tạo PR # 6251 với matplotlib để thêm một PercentFormatterlớp mới . Với lớp này, bạn chỉ cần một dòng để định dạng lại trục của mình (hai dòng nếu bạn tính lần nhập matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

ax = df['myvar'].plot(kind='bar')
ax.yaxis.set_major_formatter(mtick.PercentFormatter())

PercentFormatter()chấp nhận ba đối số, xmax, decimals, symbol. xmaxcho phép bạn đặt giá trị tương ứng với 100% trên trục. Điều này thật tuyệt nếu bạn có dữ liệu từ 0,0 đến 1,0 và bạn muốn hiển thị nó từ 0% đến 100%. Chỉ cần làm PercentFormatter(1.0).

Hai tham số còn lại cho phép bạn đặt số chữ số sau dấu thập phân và ký hiệu. Chúng mặc định thành None'%', tương ứng. decimals=Nonesẽ tự động đặt số điểm thập phân dựa trên số lượng trục bạn đang hiển thị.

Cập nhật

PercentFormatter đã được đưa vào Matplotlib ngay trong phiên bản 2.1.0.


@MateenUlhaq Vui lòng không giới thiệu các sửa đổi mã đáng kể trong các chỉnh sửa của bạn. Bạn đã sao chép mã trong câu trả lời của tôi mà không cần bất kỳ nhu cầu nào. Nó không phải là một bản chỉnh sửa tốt.
Mad Physicist

Thật tệ, vì một số lý do kỳ lạ, tôi đã đọc nó from matplotlib.ticker import mtickvà cho rằng mtick"mô-đun" đã bị xóa.
Mateen Ulhaq

125

Biểu đồ khung dữ liệu gấu trúc sẽ trả về axcho bạn, Và sau đó bạn có thể bắt đầu thao tác các trục bất cứ điều gì bạn muốn.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(100,5))

# you get ax from here
ax = df.plot()
type(ax)  # matplotlib.axes._subplots.AxesSubplot

# manipulate
vals = ax.get_yticks()
ax.set_yticklabels(['{:,.2%}'.format(x) for x in vals])

nhập mô tả hình ảnh ở đây


5
Điều này sẽ có tác dụng không mong muốn càng sớm càng tốt pan / zoom biểu đồ tương tác
hitzg

3
Dễ dàng hơn hàng triệu lần so với việc cố gắng sử dụng matplotlib.tickercác định dạng hàm!
Jarad

Làm thế nào để bạn giới hạn trục y (0,100%)? Tôi đã thử ax.set_ylim (0,100) nhưng điều đó dường như không hiệu quả !!
mpour

@mpour chỉ thay đổi nhãn của các thanh, vì vậy giới hạn vẫn ở đơn vị tự nhiên. Đặt ax.set_ylim (0, 1) sẽ thực hiện thủ thuật.
Joeran

79

Giải pháp của Jianxun đã thực hiện công việc cho tôi nhưng đã phá vỡ chỉ báo giá trị y ở phía dưới bên trái của cửa sổ.

Tôi đã kết thúc bằng cách FuncFormatterthay thế (và cũng loại bỏ các số 0 ở cuối không cần thiết như được đề xuất ở đây ):

import pandas as pd
import numpy as np
from matplotlib.ticker import FuncFormatter

df = pd.DataFrame(np.random.randn(100,5))

ax = df.plot()
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y))) 

Nói chung, tôi khuyên bạn nên sử dụng FuncFormatterđể định dạng nhãn: nó đáng tin cậy và linh hoạt.

nhập mô tả hình ảnh ở đây


19
Bạn có thể đơn giản hóa mã thậm chí nhiều hơn: ax.yaxis.set_major_formatter(FuncFormatter('{0:.0%}'.format)). AKA không cần lambda, hãy để định dạng thực hiện công việc.
Daniel Himmelstein

@DanielHimmelstein bạn có thể giải thích điều này một chút được không? Đặc biệt là bên trong {}. Không chắc làm thế nào 0,06 của tôi được chuyển thành 6% bằng cách sử dụng định dạng python. Cũng là giải pháp tuyệt vời. Có vẻ hoạt động đáng tin cậy hơn nhiều so với sử dụng .set_ticklabels
DChaps

3
@DChaps '{0:.0%}'.formattạo một chức năng định dạng . Các 0trước dấu hai chấm kể định dạng để thay thế xoăn-khung và nội dung của nó với đối số đầu tiên truyền cho hàm. Phần sau dấu hai chấm, .0%cho trình định dạng biết cách hiển thị giá trị. Chỉ .0định 0 vị trí thập phân và %chỉ định hiển thị dưới dạng phần trăm.
Daniel Himmelstein

31

Đối với những người đang tìm kiếm một lớp lót nhanh chóng:

plt.gca().set_yticklabels(['{:.0f}%'.format(x*100) for x in plt.gca().get_yticks()]) 

Hoặc nếu bạn đang sử dụng Latex làm trình định dạng văn bản trục, bạn phải thêm một dấu gạch chéo ngược '\'

plt.gca().set_yticklabels(['{:.0f}\%'.format(x*100) for x in plt.gca().get_yticks()]) 

Đối với tôi, câu trả lời của Daniel Himmelstein đã hoạt động trong khi câu trả lời này đã thay đổi thang điểm
R. Cox

2

Tôi đề xuất một phương pháp thay thế bằng cách sử dụng seaborn

Mã làm việc:

import pandas as pd
import seaborn as sns
data=np.random.rand(10,2)*100
df = pd.DataFrame(data, columns=['A', 'B'])
ax= sns.lineplot(data=df, markers= True)
ax.set(xlabel='xlabel', ylabel='ylabel', title='title')
#changing ylables ticks
y_value=['{:,.2f}'.format(x) + '%' for x in ax.get_yticks()]
ax.set_yticklabels(y_value)

nhập mô tả hình ảnh ở đây


0

Tôi đến muộn với trò chơi nhưng tôi chỉ nhận ra điều này: axcó thể được thay thế bằng plt.gca()cho những người không sử dụng trục và chỉ là các âm mưu phụ.

Echoing @Mad Physicist câu trả lời, sử dụng gói PercentFormatternó sẽ là:

import matplotlib.ticker as mtick

plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter(1))
#if you already have ticks in the 0 to 1 range. Otherwise see their answer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.