adjustText Documentation

repository·master·Indexed 23 days ago

https://github.com/phlya/adjusttext

A Python library for matplotlib that automatically adjusts the position of text labels to prevent them from overlapping with each other, data points, or other plot elements. Inspired by the ggrepel package for R/ggplot2, it provides the adjust_text function to iteratively reposition labels, with support for custom repulsion forces, bounding box expansion, movement restrictions via only_move, and compatibility with Cartopy axes.

Tokens
2.6K
Snippets
6
Records
16
Agent score
81%

What's inside adjustText

  1. Overview of adjustText

    master

    What is adjustText?

    adjustText is a library for matplotlib designed to automate label placement on graphs. It solves the problem of text labels overlapping with each other or with data points by iteratively adjusting their positions to minimize overlaps.

    Inspired by the ggrepel package for R/ggplot2, it provides a straightforward way to improve the readability of plots containing multiple labels without requiring manual adjustment.

  2. What is adjustText?

    master
    adjustText is a Python library designed to automatically adjust text positions on matplotlib plots. Its primary purpose is to remove or minimize overlaps between text labels, data points, and other plot elements. It achieves this by calculating bounding box overlaps and iteratively moving text elements to reduce these overlaps. The logic is inspired by the ggrepel package for R/ggplot2.
  3. Install adjustText

    master

    You can install adjustText using pip, conda, or directly from the GitHub repository.

    Using pip

    pip install adjustText

    Using conda

    conda install -c conda-forge adjusttext

    Installing the latest version from GitHub

    pip install https://github.com/Phlya/adjustText/archive/master.zip
    pip install adjustText
  4. Repel text from other objects using add_objects

    master
    By default, adjust_text repels text from other text objects and points. You can also tell it to avoid other Matplotlib objects (like Patch objects used for bars or custom Rectangle patches) by passing them in the add_objects list. The algorithm uses the objects' bounding boxes to calculate repulsion.
  5. Restrict text movement with only_move

    master

    You can control which axes the text, points, or other objects are allowed to move along using the only_move parameter. This is useful when you want to keep labels aligned with specific features (like bars) or prevent them from shifting horizontally/vertically.

    only_move accepts a dictionary with keys: 'points', 'text', and 'objects'. The values can be 'x', 'y', or '' (to allow movement in both directions).

  6. Adjust text for multiple subplots

    master

    When working with multiple subplots in matplotlib, you cannot pass all text objects from all subplots to a single adjust_text call. Instead, you must iterate through each subplot (axis) and call adjust_text individually for the text objects belonging to that specific axis.

    To do this, pass the specific axis object to the ax parameter of adjust_text to ensure the adjustment logic is scoped to the correct subplot.

  7. Basic usage of adjust_text

    master

    To use adjust_text, first create your matplotlib text objects using ax.text() or plt.text(), collect them in a list, and then pass that list to the adjust_text() function. This will automatically reposition the labels to reduce overlap.

    import matplotlib.pyplot as plt
    from adjustText import adjust_text
    import numpy as np
    
    # Setup data and plot
    np.random.seed(0)
    x, y = np.random.random((2,30))
    fig, ax = plt.subplots()
    ax.plot(x, y, 'bo')
    
    # Create text objects
    texts = [ax.text(x[i], y[i], 'Text%s' %i, ha='center', va='center') for i in range(len(x))]
    
    # Adjust the text
    adjust_text(texts)
    import matplotlib.pyplot as plt
    from adjustText import adjust_text
    import numpy as np
    
    np.random.seed(0)
    x, y = np.random.random((2,30))
    fig, ax = plt.subplots()
    ax.plot(x, y, 'bo')
    
    texts = [ax.text(x[i], y[i], 'Text%s' %i, ha='center', va='center') for i in range(len(x))]
    adjust_text(texts);
  8. Use adjust_text to resolve label overlaps

    master
    The core functionality of the library is provided by the adjust_text function within the adjustText module. This function takes text objects from a matplotlib plot and iteratively repositions them to minimize overlaps with each other and with data points.
  9. Use adjust_text with Cartopy axes

    master

    The adjust_text function is compatible with cartopy projection axes. Ensure you pass the specific ax object to the function.

    import cartopy.crs as ccrs
    
    fig = plt.figure(figsize=[10, 8])
    ax = plt.subplot(1, 1, 1, projection=ccrs.NorthPolarStereo())
    # ... setup map and scatter ...
    
    texts = [ax.text(lon, lat, 'Label', transform=ccrs.PlateCarree()) for lon, lat in zip(lons, lats)]
    
    adjust_text(texts, arrowprops=dict(arrowstyle='->', color='blue'), ax=ax)
    import cartopy.crs as ccrs
    fig = plt.figure(figsize=[10, 8])
    ax = plt.subplot(1, 1, 1, projection=ccrs.NorthPolarStereo())
    ax.coastlines(resolution='50m')
    ax.set_extent([-180,180,53,90],crs=ccrs.PlateCarree())
    
    np.random.seed(0)
    loclon = np.random.randint(-180, 180, 25)
    loclat = np.random.randint(53, 90, 25)
    ax.scatter(loclon, loclat, transform=ccrs.PlateCarree())
    
    texts = [ax.text(loclon[i], loclat[i], 'Location%s' %i, ha='center', color='r', 
                va='center', transform=ccrs.PlateCarree()) for i in range(len(loclon))]
    
    adjust_text(texts, arrowprops=dict(arrowstyle='->', color='blue'), ax=ax);
  10. Restrict label movement with only_move

    master

    To keep labels aligned with specific features (like bar charts or time series), you can restrict their movement to a single axis using the only_move parameter.

    • only_move='x-': Move labels only to the left.
    • only_move='y+': Move labels only upwards.

    This is useful when you want to maintain vertical alignment with bars or horizontal alignment with a timeline.

    # Example: Moving labels only to the left to avoid a vertical line of points
    adjust_text(texts, 
                x=[0 for _ in df], 
                y=df, 
                only_move='x-', 
                expand=(1, 1), 
                force_text=(0.5, 0))
    adjust_text(texts, x=[0 for _ in df], y=df, avoid_self=False,
                force_text=(0.5, 0),
                expand=(1, 1),
                only_move='x-', 
                max_move=None
    );
  11. Repel labels from matplotlib objects like bars

    master

    You can prevent labels from overlapping with specific matplotlib objects (like BarContainer from ax.bar()) by using the add_objects parameter. This uses the objects' bounding boxes for repulsion.

    # Plotting bars
    bars = ax.bar(x, y, color='green')
    
    # Create text labels
    texts = []
    for j, rect in enumerate(bars):
        left = rect.get_x() + 1
        top = rect.get_y() + rect.get_height()
        texts.append(ax.text(left, top, '%.3f' % y[j], ha='center', va='bottom'))
    
    # Adjust text while avoiding the bars and restricting movement to the y-axis
    adjust_text(texts, 
                add_objects=bars, 
                only_move='y+', 
                ax=ax)