简体   繁体   中英

Python Matplotlib : how to put label next to each element in the bubble plot

I have bubble plot like this, and I am willing to put labels next to each bubble (their name). Does any body know how to do that?

在此处输入图片说明

@Falko refered to another post that indicates you should be looking for the text method of the axes. However, your problem is quite a bit more involved than that, because you'll need to implement an offset that scales dynamically with the size of the "bubble" (the marker). That means you'll be looking into the transformation methods of matplotlib.

As you didn't provide a simple example dataset to experiment with, I've used one that is freely available: earthquakes of 1974. In this example, I'm plotting the depth of the quake vs the date on which it occurred, using the magnitude of the earthquake as the size of the bubbles/markers. I'm appending the locations of where these earthquakes happened next to the markers , not inside (which is far more easy: ignore the offset and set ha='center' in the call to ax.text ).

Note that the bulk of this code example is merely about getting some dataset to toy with. What you really needed was just the ax.text method with the offset.

from __future__ import division  # use real division in Python2.x
from matplotlib.dates import date2num
import matplotlib.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Get a dataset
data_url = 'http://datasets.flowingdata.com/earthquakes1974.csv'
df = pd.read_csv(data_url, parse_dates=['time'])
# Select a random subset of that dataframe to generate some variance in dates, magnitudes, ...
data = np.random.choice(df.shape[0], 10)
records = df.loc[data]
# Taint the dataset to add some bigger variance in the magnitude of the 
# quake to show that the offset varies with the size of the marker
records.mag.values[:] = np.arange(10)
records.mag.values[0] = 50
records.mag.values[-1] = 100

dates = [date2num(dt) for dt in records.time]
f, ax = plt.subplots(1,1)
ax.scatter(dates, records.depth, s=records.mag*100, alpha=.4)  # markersize is given in points**2 in recentt versions of mpl
for _, record in records.iterrows():
    # Specify an offset for the text annotation:
    # it is approx the radius of the disc + 10 points to the right
    dx, dy = np.sqrt(record.mag*100)/f.dpi/2 + 10/f.dpi, 0.  
    offset = transforms.ScaledTranslation(dx, dy, f.dpi_scale_trans)
    ax.text(date2num(record.time), record.depth, s=record.place,
        va='center',  ha='left',
        transform=ax.transData + offset)
ax.set_xticks(dates)
ax.set_xticklabels([el.strftime("%Y-%M") for el in records.time], rotation=-60)
ax.set_ylabel('depth of earthquake')
plt.show()

For one such run, I got: 气泡图中的地震数据,标记右侧有标签 Definitely not pretty because of the overlapping labels, but it was just an example to show how to use the transforms in matplotlib to dynamically add an offset to the labels.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM