“Clean” way to use words as markers in matplotlib? And make font size and color differ?

前端 未结 2 588
逝去的感伤
逝去的感伤 2021-01-05 15:35

Suppose I have the 3x3 matrix below:

[apples 19 3.5]

[oranges 07 2.2]

[grapes 23 7.8]

Only in real life the matrix has dozens of rows, not ju

2条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-05 16:13

    While looking around for a solution to the same problem, I've found one that seems a bit cleaner (or at least more in spirit to what the original question asked), namely to use TextPath:

    from matplotlib import pyplot as plt
    from matplotlib.text import TextPath
    
    data = [["peach", 1.0, 1.0], 
            ["apples", 19, 3.5], 
            ["oranges", 7, 2.2], 
            ["grapes", 23, 7.8]]
    
    max_d2 = max([d[2] for d in data]) + 1e-3
    max_d1 = max([d[1] for d in data]) + 1e-3
    
    cmap = plt.get_cmap('RdBu')
    for d in data:
        path = TextPath((0,0), d[0])
    
        # These dots are to display the weakness below, remove for the actual question
        plt.plot(d[1],d[2],'.',color='k')
    
        plt.plot(d[1],d[2],marker=path,markersize=100, color=cmap(d[2]/max_d2))
    plt.xlim([0,max_d1+5])
    plt.ylim([0,max_d2+0.5])
    

    This solution has some advantages and disadvantages of its own:

    • Main disadvantage: as the dots show, I wasn't able to properly center the text as I wanted. Instead, the required value is the bottom left of the picture.
    • Main advantage: this has no latex issue and uses a "real" marker path, which means that it can easily be used to e.g. mark line plots (not the original question, though)

    Code:

    import numpy as np
    x = np.cumsum(np.random.randn(100,5), axis=0)
    
    plt.figure(figsize=(15,5))
    for i in range(5):
        label = TextPath((0,0), str(i), linewidth=1)
        plt.plot(x[:,i], color='k')
        plt.plot(np.arange(0,len(x),5),x[::5,i], color='k', marker=label, markersize=15, linewidth=0)
    

    Doing the above via a naive loop over "text" or "annotate" would be very slow if you had many lines / markers, while this scales better.

提交回复
热议问题