在 Python 中自动将文本添加到 matplotlib 图

Automatic add text to matplotlib plot in Python

我尝试制作一个图,并希望自动将文本(在本例中为百分比)添加到与每个 y 轴类型相对应的每个圆圈。任何帮助都会很有帮助。

# import libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
# Make some data
index=['Stream flow',
 'Soil moisture',
 'Water indices',
 'Others',
 'Temperature',
 'Precipitation',
 'Vegetative indices']
value=[2.13, 6.38, 10.64, 12.77, 17.73, 21.99, 28.37]

# create dataframe
percentages = pd.Series(value,index=index)
df = pd.DataFrame({'percentage' : percentages})
df = df.sort_values(by='percentage')

# we first need a numeric placeholder for the y axis
my_range=list(range(1,len(df.index)+1))

fig, ax = plt.subplots(figsize=(15,8))

# create for each expense type an horizontal line that starts at x = 0 with the length 
plt.hlines(y=my_range, xmin=0, xmax=df['percentage']-0.5, color='black', alpha=0.8, linewidth=1)

# create for each expense type a dot at the level of the expense percentage value
line=plt.plot(df['percentage'], my_range, "o", markersize=30, color='#fd8c00', alpha=0.6, linewidth=0.3)

# set labels
ax.set_xlabel('Percentage', fontsize=15)
ax.set_ylabel('')

# set axis
ax.tick_params(axis='both', which='major', labelsize=14)
plt.yticks(my_range, df.index)


ax.set_xlim(0,30)

您可以使用 matplotlib.axes.Axes.text:

x_space = 0.4
y_space = 0.05
fontsize = 7
for y_i, val in enumerate(value, 1):
    ax.text(x = val - x_space, y = y_i - y_space, s = f'{val}%', fontsize = fontsize)

您必须调整 x_spacey_spacefontsize 才能使文本正确适合圆圈。

完整代码

# import libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
# Make some data
index=['Stream flow',
 'Soil moisture',
 'Water indices',
 'Others',
 'Temperature',
 'Precipitation',
 'Vegetative indices']
value=[2.13, 6.38, 10.64, 12.77, 17.73, 21.99, 28.37]

# create dataframe
percentages = pd.Series(value,index=index)
df = pd.DataFrame({'percentage' : percentages})
df = df.sort_values(by='percentage')

# we first need a numeric placeholder for the y axis
my_range=list(range(1,len(df.index)+1))

fig, ax = plt.subplots(figsize=(15,8))

# create for each expense type an horizontal line that starts at x = 0 with the length 
plt.hlines(y=my_range, xmin=0, xmax=df['percentage']-0.5, color='black', alpha=0.8, linewidth=1)

# create for each expense type a dot at the level of the expense percentage value
line=plt.plot(df['percentage'], my_range, "o", markersize=30, color='#fd8c00', alpha=0.6, linewidth=0.3)

# set labels
ax.set_xlabel('Percentage', fontsize=15)
ax.set_ylabel('')

# set axis
ax.tick_params(axis='both', which='major', labelsize=14)
plt.yticks(my_range, df.index)

ax.set_xlim(0,30)


x_space = 0.4
y_space = 0.05
for y_i, val in enumerate(value, 1):
    ax.text(x = val - x_space, y = y_i - y_space, s = f'{val:>5.2f}%', fontsize = 7)


plt.show()


与上面的代码相同,但增加了圆半径和字体,以提高可读性。

# import libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
# Make some data
index=['Stream flow',
 'Soil moisture',
 'Water indices',
 'Others',
 'Temperature',
 'Precipitation',
 'Vegetative indices']
value=[2.13, 6.38, 10.64, 12.77, 17.73, 21.99, 28.37]

# create dataframe
percentages = pd.Series(value,index=index)
df = pd.DataFrame({'percentage' : percentages})
df = df.sort_values(by='percentage')

# we first need a numeric placeholder for the y axis
my_range=list(range(1,len(df.index)+1))

fig, ax = plt.subplots(figsize=(15,8))

# create for each expense type an horizontal line that starts at x = 0 with the length 
plt.hlines(y=my_range, xmin=0, xmax=df['percentage']-0.85, color='black', alpha=0.8, linewidth=1)

# create for each expense type a dot at the level of the expense percentage value
line=plt.plot(df['percentage'], my_range, "o", markersize=50, color='#fd8c00', alpha=0.6, linewidth=0.3)

# set labels
ax.set_xlabel('Percentage', fontsize=15)
ax.set_ylabel('')

# set axis
ax.tick_params(axis='both', which='major', labelsize=14)
plt.yticks(my_range, df.index)

ax.set_xlim(0,30)
ax.set_ylim(0, len(value) + 1)

x_space = 0.75
y_space = 0.06
fontsize = 12
for y_i, val in enumerate(value, 1):
    ax.text(x = val - x_space, y = y_i - y_space, s = f'{val:>5.2f}%', fontsize = fontsize)


plt.show()


更好的是,您可以使用 matplotlib.axes.Axes.annotate 来摆脱 x_spacey_space:

fontsize = 12
for y_i, x_i in enumerate(value, 1):
    ax.annotate(f'{x_i:>5.2f}%', xy = (x_i, y_i), xytext = (0, 0), textcoords = 'offset points', ha = 'center', va = 'center', fontsize = fontsize)

您仍然需要调整 fontsize 以适合圆的半径。