Search code examples
numpymatplotliblogarithmradar-chart

Matplotlib Logarithmic Radar Charts - Remove all values below 0.5 and show last ytick


If you look in the logarithmic radar chart below, there are two changes I would like, if anyone knows the correct way to code:

1)Display a ytick label for the max value (51.81), as it currently gives the top value as 31.62

2)A way to set all values below 0.1 to 0, without causing divide by zero errors.

fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, polar=True)
np.seterr(divide = 'warn') 

sample = samplelistmalshare

get_mag = lambda x: 10**min(np.floor(np.log10(x)))
init_mag = get_mag(sample)
print("init_mag")
print(init_mag)
print("gm")
print(get_mag)

sample = np.array(sample) / get_mag(sample)
N = len(sample)

theta = np.arange(0, 2 * np.pi, 2 * np.pi / N)


bars = ax.bar(theta, np.log10(sample), width=0.4, color = '#003F5C')


ax.set_xticks(theta)
ax.set_xticklabels(['           Delayed\n           Execution', '            File\n            Opening', 'Firewall\nModification', 'Permission              \nModification              ', 'Persistence                 ', 'Proxied          \nExecution           ', 'Reconnaissance          ', '    Registry\n    Modification', '    Task\n    Stopping'], visible=False)

dat = np.log10(sample)
print(max(dat))
#exit()
ax.set_ylim(0,max(dat))
ax.xaxis.grid(False)

ax.yaxis.grid(True)
precision = 2  # Change to your desired decimal precision

ax.set_yticklabels([str(round((10 ** x) * init_mag, precision)) for x in ax.get_yticks()])

for test in ax.get_yticks():
  print(test)


for test in ax.get_ymajorticklabels():
  print(test) 
ax.set_rlabel_position(50)
plt.savefig('radarchartingmalshare.pdf',bbox_inches='tight')
fig.clf()
plt.clf()

enter image description here


Solution

  • One solution is to set yticks and yticklabels manually

    right_end = 51.81 
    
    ax.set_ylim(0,np.log10(right_end / init_mag))
    y_ticks = np.linspace(0,np.log10(right_end/init_mag),10)
    ax.set_yticks(y_ticks)
    y_ticklabels = ['%.2f' % (init_mag*10**x) if x !=0 else '0.00' for x in ax.get_yticks()]
    ax.set_yticklabels(y_ticklabels)
    

    With this manually set ticks and the labels

    import numpy as np
    from matplotlib import pyplot as plt 
    
    
    fig = plt.figure(figsize=(8, 8));
    ax = fig.add_subplot(111, polar=True)
    np.seterr(divide = 'warn') 
    
    sample = [35.417256011315416,0.028288543140028287,1.3578500707213579,3.3663366336633667,
              0.8203677510608205,35.445544554455445,3.3946251768033946,19.46251768033946,0.7072135785007072,]
    
    get_mag = lambda x: 10**min(np.floor(np.log10(x)))
    init_mag = get_mag(sample)
    sample = np.array(sample) / get_mag(sample)
    dat = np.log10(sample)
    N = len(sample)
    
    theta = np.arange(0, 2 * np.pi, 2 * np.pi / N)
    bars = ax.bar(theta, dat, width=0.4, color = 'deepskyblue')
    
    ax.set_xticks(theta)
    ax.xaxis.grid(False)
    
    right_end = 51.81 
    ax.set_ylim(0,np.log10(right_end / init_mag))
    ax.yaxis.grid(True)
    
    y_ticks = np.linspace(0,np.log10(right_end/init_mag),10)
    ax.set_yticks(y_ticks)
    y_ticklabels = ['%.2f' % (init_mag*10**x) if x !=0 else '0.00' for x in ax.get_yticks()]
    ax.set_yticklabels(y_ticklabels)
    ax.tick_params(axis='y',colors='darkviolet')
    
    plt.show()
    

    output