科研绘图代码分享

科研绘图代码

1️⃣代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
2️⃣部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
3️⃣感谢在我科研绘图过程中提供帮助的各位博主!
(1)扇形图自定义色彩条
(2)组合图(4x2)
(3)堆积柱状图
(4)混淆矩阵
(5)局部放大+图中注释+折线图
(6)糖葫芦图
(7)横向柱状图+折线图
(8)雷达图
(9)多组柱状图
(10)双向柱状图
(11)三维柱状图
(12)构建平面直角坐标系

源代码下载链接(链接失效可留言或私信):https://wwgh.lanzouw.com/iFHow1g0es7c?w1

环境信息

alabaster==0.7.12
anaconda-client==1.7.2
anaconda-navigator==1.10.0
anaconda-project==0.8.3
argh==0.26.2
argon2-cffi @ file:///C:/ci/argon2-cffi_1596828585465/work
asn1crypto @ file:///tmp/build/80754af9/asn1crypto_1596577642040/work
astroid @ file:///C:/ci/astroid_1592487315634/work
astropy==4.0.2
async-generator==1.10
atomicwrites==1.4.0
attrs @ file:///tmp/build/80754af9/attrs_1604765588209/work
autopep8 @ file:///tmp/build/80754af9/autopep8_1596578164842/work
Babel @ file:///tmp/build/80754af9/babel_1605108370292/work
backcall==0.2.0
backports.functools-lru-cache==1.6.1
backports.shutil-get-terminal-size==1.0.0
backports.tempfile==1.0
backports.weakref==1.0.post1
bcrypt @ file:///C:/ci/bcrypt_1597936263757/work
beautifulsoup4 @ file:///tmp/build/80754af9/beautifulsoup4_1601924105527/work
bitarray @ file:///C:/ci/bitarray_1605065210072/work
bkcharts==0.2
bleach @ file:///tmp/build/80754af9/bleach_1600439572647/work
bokeh @ file:///C:/ci/bokeh_1603297934731/work
boto==2.49.0
Bottleneck==1.3.2
brotlipy==0.7.0
certifi==2020.6.20
cffi @ file:///C:/ci/cffi_1600699246375/work
chardet==3.0.4
click==7.1.2
cloudpickle @ file:///tmp/build/80754af9/cloudpickle_1598884132938/work
clyent==1.2.2
colorama @ file:///tmp/build/80754af9/colorama_1603211150991/work
comtypes==1.1.7
conda==4.9.2
conda-build==3.20.5
conda-package-handling @ file:///C:/ci/conda-package-handling_1603003327818/work
conda-verify==3.4.2
contextlib2==0.6.0.post1
cryptography @ file:///C:/ci/cryptography_1601046905460/work
cycler==0.10.0
Cython @ file:///C:/ci/cython_1594829190914/work
cytoolz==0.11.0
dask @ file:///tmp/build/80754af9/dask-core_1602083700509/work
decorator==4.4.2
defusedxml==0.6.0
diff-match-patch @ file:///tmp/build/80754af9/diff-match-patch_1594828741838/work
distributed @ file:///C:/ci/distributed_1605066635297/work
docutils==0.16
entrypoints==0.3
et-xmlfile==1.0.1
fastcache==1.1.0
filelock==3.0.12
flake8 @ file:///tmp/build/80754af9/flake8_1601911421857/work
Flask==1.1.2
fsspec @ file:///tmp/build/80754af9/fsspec_1602684995936/work
future==0.18.2
gevent @ file:///C:/ci/gevent_1601397627942/work
glob2==0.7
greenlet @ file:///C:/ci/greenlet_1600885448389/work
h5py==2.10.0
HeapDict==1.0.1
html5lib @ file:///tmp/build/80754af9/html5lib_1593446221756/work
idna @ file:///tmp/build/80754af9/idna_1593446292537/work
imageio @ file:///tmp/build/80754af9/imageio_1594161405741/work
imagesize==1.2.0
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1602276842396/work
iniconfig @ file:///tmp/build/80754af9/iniconfig_1602780191262/work
intervaltree @ file:///tmp/build/80754af9/intervaltree_1598376443606/work
ipykernel @ file:///C:/ci/ipykernel_1596190155316/work/dist/ipykernel-5.3.4-py3-none-any.whl
ipython @ file:///C:/ci/ipython_1604083276484/work
ipython-genutils==0.2.0
ipywidgets @ file:///tmp/build/80754af9/ipywidgets_1601490159889/work
isort @ file:///tmp/build/80754af9/isort_1602603989581/work
itsdangerous==1.1.0
jdcal==1.4.1
jedi @ file:///C:/ci/jedi_1592833825077/work
Jinja2==2.11.2
joblib @ file:///tmp/build/80754af9/joblib_1601912903842/work
json5==0.9.5
jsonschema @ file:///tmp/build/80754af9/jsonschema_1602607155483/work
jupyter==1.0.0
jupyter-client @ file:///tmp/build/80754af9/jupyter_client_1601311786391/work
jupyter-console @ file:///tmp/build/80754af9/jupyter_console_1598884538475/work
jupyter-core==4.6.3
jupyterlab==2.2.6
jupyterlab-pygments @ file:///tmp/build/80754af9/jupyterlab_pygments_1601490720602/work
jupyterlab-server @ file:///tmp/build/80754af9/jupyterlab_server_1594164409481/work
keyring @ file:///C:/ci/keyring_1601489747083/work
kiwisolver @ file:///C:/ci/kiwisolver_1604014703538/work
lazy-object-proxy==1.4.3
libarchive-c==2.9
llvmlite==0.34.0
locket==0.2.0
lxml @ file:///C:/ci/lxml_1603216366346/work
MarkupSafe==1.1.1
matplotlib @ file:///C:/ci/matplotlib-base_1603355780617/work
mccabe==0.6.1
menuinst==1.4.16
mistune==0.8.4
mkl-fft==1.2.0
mkl-random==1.1.1
mkl-service==2.3.0
mock==4.0.2
more-itertools @ file:///tmp/build/80754af9/more-itertools_1605111547926/work
mpmath==1.1.0
msgpack==1.0.0
multipledispatch==0.6.0
navigator-updater==0.2.1
nbclient @ file:///tmp/build/80754af9/nbclient_1602783176460/work
nbconvert @ file:///C:/ci/nbconvert_1601914925608/work
nbformat @ file:///tmp/build/80754af9/nbformat_1602783287752/work
nest-asyncio @ file:///tmp/build/80754af9/nest-asyncio_1605115881283/work
networkx @ file:///tmp/build/80754af9/networkx_1598376031484/work
nltk @ file:///tmp/build/80754af9/nltk_1592496090529/work
nose==1.3.7
notebook @ file:///C:/ci/notebook_1601501643625/work
numba==0.51.2
numexpr==2.7.1
numpy @ file:///C:/ci/numpy_and_numpy_base_1603466732592/work
numpydoc @ file:///tmp/build/80754af9/numpydoc_1605117425582/work
olefile==0.46
openpyxl @ file:///tmp/build/80754af9/openpyxl_1598113097404/work
packaging==20.4
pandas @ file:///C:/ci/pandas_1602083338010/work
pandocfilters @ file:///C:/ci/pandocfilters_1605102497129/work
paramiko @ file:///tmp/build/80754af9/paramiko_1598886428689/work
parso==0.7.0
partd==1.1.0
path @ file:///C:/ci/path_1598358556930/work
pathlib2==2.3.5
pathtools==0.1.2
patsy==0.5.1
pep8==1.7.1
pexpect==4.8.0
pickleshare==0.7.5
Pillow @ file:///C:/ci/pillow_1603823068645/work
pkginfo==1.6.1
pluggy==0.13.1
ply==3.11
prometheus-client==0.8.0
prompt-toolkit @ file:///tmp/build/80754af9/prompt-toolkit_1602688806899/work
psutil @ file:///C:/ci/psutil_1598370330503/work
py @ file:///tmp/build/80754af9/py_1593446248552/work
pycodestyle==2.6.0
pycosat==0.6.3
pycparser @ file:///tmp/build/80754af9/pycparser_1594388511720/work
pycurl==7.43.0.6
pydocstyle @ file:///tmp/build/80754af9/pydocstyle_1598885001695/work
pyflakes==2.2.0
Pygments @ file:///tmp/build/80754af9/pygments_1604103097372/work
pylint @ file:///C:/ci/pylint_1598617153160/work
PyNaCl @ file:///C:/ci/pynacl_1595000047588/work
pyodbc===4.0.0-unsupported
pyOpenSSL @ file:///tmp/build/80754af9/pyopenssl_1594392929924/work
pyparsing==2.4.7
pyreadline==2.1
pyrsistent @ file:///C:/ci/pyrsistent_1600141795814/work
PySocks==1.7.1
pytest==0.0.0
python-dateutil==2.8.1
python-jsonrpc-server @ file:///tmp/build/80754af9/python-jsonrpc-server_1600278539111/work
python-language-server @ file:///tmp/build/80754af9/python-language-server_1600454544709/work
pytz==2020.1
PyWavelets @ file:///C:/ci/pywavelets_1601658407916/work
pywin32==227
pywin32-ctypes==0.2.0
pywinpty==0.5.7
PyYAML==5.3.1
pyzmq==19.0.2
QDarkStyle==2.8.1
QtAwesome @ file:///tmp/build/80754af9/qtawesome_1602272867890/work
qtconsole @ file:///tmp/build/80754af9/qtconsole_1600870028330/work
QtPy==1.9.0
regex @ file:///C:/ci/regex_1602770567298/work
requests @ file:///tmp/build/80754af9/requests_1592841827918/work
rope @ file:///tmp/build/80754af9/rope_1602264064449/work
Rtree==0.9.4
ruamel-yaml==0.15.87
scikit-image==0.17.2
scikit-learn @ file:///C:/ci/scikit-learn_1598377018496/work
scipy @ file:///C:/ci/scipy_1604596260408/work
seaborn @ file:///tmp/build/80754af9/seaborn_1600553570093/work
Send2Trash==1.5.0
simplegeneric==0.8.1
singledispatch @ file:///tmp/build/80754af9/singledispatch_1602523705405/work
sip==4.19.13
six @ file:///C:/ci/six_1605187374963/work
snowballstemmer==2.0.0
sortedcollections==1.2.1
sortedcontainers==2.2.2
soupsieve==2.0.1
Sphinx @ file:///tmp/build/80754af9/sphinx_1597428793432/work
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==1.0.3
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.4
sphinxcontrib-websupport @ file:///tmp/build/80754af9/sphinxcontrib-websupport_1597081412696/work
spyder @ file:///C:/ci/spyder_1599054115447/work
spyder-kernels @ file:///C:/ci/spyder-kernels_1599051709837/work
SQLAlchemy @ file:///C:/ci/sqlalchemy_1603818908746/work
statsmodels==0.12.0
sympy @ file:///C:/ci/sympy_1605101511098/work
tables==3.6.1
tblib @ file:///tmp/build/80754af9/tblib_1597928476713/work
terminado==0.9.1
testpath==0.4.4
threadpoolctl @ file:///tmp/tmp9twdgx9k/threadpoolctl-2.1.0-py3-none-any.whl
tifffile==2020.10.1
toml @ file:///tmp/build/80754af9/toml_1592853716807/work
toolz @ file:///tmp/build/80754af9/toolz_1601054250827/work
tornado==6.0.4
tqdm @ file:///tmp/build/80754af9/tqdm_1602185206534/work
traitlets @ file:///tmp/build/80754af9/traitlets_1602787416690/work
typing-extensions @ file:///tmp/build/80754af9/typing_extensions_1598376058250/work
ujson @ file:///C:/ci/ujson_1602505266082/work
unicodecsv==0.14.1
urllib3 @ file:///tmp/build/80754af9/urllib3_1603305693037/work
watchdog @ file:///C:/ci/watchdog_1593447437088/work
wcwidth @ file:///tmp/build/80754af9/wcwidth_1593447189090/work
webencodings==0.5.1
Werkzeug==1.0.1
widgetsnbextension==3.5.1
win-inet-pton==1.1.0
win-unicode-console==0.5
wincertstore==0.2
wrapt==1.11.2
xlrd==1.2.0
XlsxWriter @ file:///tmp/build/80754af9/xlsxwriter_1602692860603/work
xlwings==0.20.8
xlwt==1.3.0
xmltodict==0.12.0
yapf @ file:///tmp/build/80754af9/yapf_1593528177422/work
zict==2.0.0
zipp @ file:///tmp/build/80754af9/zipp_1604001098328/work
zope.event==4.5.0
zope.interface @ file:///C:/ci/zope.interface_1602002494740/work

(1)扇形图自定义色彩条

# 代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
# 部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
# 感谢在我科研绘图过程中提供帮助的各位博主!

# 导包
import matplotlib.pyplot as plt
from matplotlib import rcParams

# 设置配置文件
config = {
    # 衬线字体(衬线字体, 宋体和Times New Roman属于这类字体)
    "font.family": 'serif',
    # matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
    "mathtext.fontset": 'stix',
    # 设置绘图时全局字体为宋体(SimSun)
    "font.serif": ['SimSun'],
}
# 修改运行时配置参数的方法(Matplotlib使用matplotlibrc配置文件来自定义图形的各种属性,称之为rc配置或rc参数(rcParams))
rcParams.update(config)
# 为每个扇形提供颜色,颜色顺序与排序后的x顺序对应
colors = ['#c4cc38', '#ebe12a', '#ebe12a', '#ebe12a', '#eab026', '#e3852b', '#d85d2a', '#ce2626']


def draw_pic(x, y):
    # 绘制饼图
    '''
    plt.pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
    startangle=0, radius=1, counterclock=True, wedgeprops=None, textprops=None, center=0, 0, frame=False,
    rotatelabels=False, *, normalize=None, data=None)
    传入的参数y为每个扇形的占比数组;
    labels为每个扇形提供标签的字符串序列;
    autopct如果是一个格式字符串,标签将是fmt % pct。如果它是一个函数,它将被调用。在代码中%0.1f%%表示保留1位小数;
    colors为每个扇形提供颜色;
    wedgeprops设置饼图内外边界的属性,如边界线的粗细、颜色等。在代码中,我们设置边框为黑色;
    textprops设置饼图中文本的属性,如字体大小、颜色等。在代码中,我们设置字号为12,字体为新罗马;
    labeldistance设置各扇形标签(图例)与圆心的距离。
    '''
    plt.pie(y, labels=x, autopct="%0.1f%%", colors=colors, wedgeprops={'edgecolor': "black"},
            textprops={'fontsize': 12, 'fontproperties': 'Times New Roman'}, labeldistance=1.05)
    # 关闭坐标轴
    plt.axis('off')
    # Matplotlib自定义添加colorbar
    # 添加子图plt.axis([a, b, c, d]) 设置x轴的范围为[a, b],y轴的范围为[c, d]
    cax = plt.axes([0.805, 0.25, 0.03, 0.5])
    '''
    fill_between用于在两条曲线间填充颜色
    fill_between(y, x1, x2=0, where=None, step=None, interpolate=False,
             data=None, **kwargs)
    y:表示y轴坐标的序列;
    x1:表示第一条曲线的x轴坐标;
    x2:表示第二条曲线的x轴坐标;
  ·where:布尔值,表示要填充区域的条件。
    '''
    cax.fill_between([0, 0.5], 0.5, color=colors[7])
    cax.fill_between([0, 0.5], 0.5, 1, color=colors[6])
    cax.fill_between([0, 0.5], 1, 1.5, color=colors[5])
    cax.fill_between([0, 0.5], 1.5, 2, color=colors[4])
    cax.fill_between([0, 0.5], 2, 2.5, color=colors[3])
    cax.fill_between([0, 0.5], 2.5, 3, color=colors[0])
    # 设置y轴正向显示范围
    cax.set_ylim(0, 3)
    # 设置x轴和y轴刻度
    cax.set_xticks([])
    cax.set_yticks([0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0])
    cax.set_yticklabels(['高频', '', '', ' ', '', '', '低频'], fontsize=12)
    # 将y轴的数值显示在右边
    cax.yaxis.tick_right()
    # 获取y轴所有刻度信息
    yticks = cax.yaxis.get_major_ticks()
    # # 隐藏第1~第5个刻线
    yticks[1].set_visible(False)
    yticks[2].set_visible(False)
    yticks[3].set_visible(False)
    yticks[4].set_visible(False)
    yticks[5].set_visible(False)
    # 存储为SVG格式(矢量图不失真),bbox_inches='tight', pad_inches=0可以去除图片的白边
    plt.savefig('扇形图自定义色彩条.svg', bbox_inches='tight', pad_inches=0)
    # plt.savefig('扇形图自定义色彩条.png', bbox_inches='tight', pad_inches=0,dpi=1200)
    plt.show()


if __name__ == '__main__':
    # 待统计序列
    feature_list = ['IRC', 'SPAM', 'CF', 'IRC', 'SPAM', 'CF', 'IRC', 'PS', 'US', 'IRC', 'DDoS', 'US', 'SPAM', 'PS',
                    'HTTP',
                    'PS', 'HTTP', 'PS', 'IRC', 'SPAM', 'CF', 'PS', 'IRC', 'DDoS', 'US', 'IRC', 'DDoS', 'US', 'P2P',
                    'SPAM',
                    'PS', 'HTTP']
    # 统计待统计序列中每类的频数,存放在字典a中
    a = {}
    for i in feature_list:
        a[i] = feature_list.count(i)
    # print(a)
    # 字典按值排序,将排序后的字典按照key和value的对应关系存放在a_order中
    a_order = sorted(a.items(), key=lambda x: x[1])
    # print(a_order)
    # 分别将a_order中每个元组的第一项和第二项,存放在x,y中,即x为每类名称,y为对应的频数
    x = []
    y = []
    for i in range(len(a_order)):
        x.append(a_order[i][0])
        y.append(a_order[i][1])
    # print(x, y)
    # 绘图
    draw_pic(x, y)

在这里插入图片描述

(2)组合图

import pandas as pd
import os
import matplotlib.pyplot as plt
from matplotlib import rcParams

config = {
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
}
rcParams.update(config)

'''matplotlib多图组合'''
data = pd.read_csv('./capture20110815.binetflow')
# data = pd.read_csv(r'D:\JetBrains\dataset\按时间排序后的CTU-13\9\capture20110817.binetflow')
# my_font = font_manager.FontProperties(fname=r'D:\JetBrains\PycharmProjects\Botnet_Traffic_Analysis\data\SimHei.ttf')
a = ['StartTime', 'Dur', 'Proto', 'SrcAddr', 'Sport', 'Dir', 'DstAddr',
     'Dport', 'State', 'sTos', 'dTos', 'TotPkts', 'TotBytes', 'SrcBytes',
     'Label']

plt.figure(1, figsize=(16, 15))
# 321表示3行2列1图
ax1 = plt.subplot(321)
ax2 = plt.subplot(322)
ax3 = plt.subplot(323)
ax4 = plt.subplot(324)
ax5 = plt.subplot(325)
ax6 = plt.subplot(326)


# plt.subplots_adjust(wspace=0.15,hspace=0.33)


def show_StartTime():
    # 统计各时间段数量
    time_dict = {}
    time_data = data['StartTime'].str[11:16]
    time_dict['10-11'] = time_data[time_data < '11:00'].shape[0]
    time_dict['11-12'] = time_data[(time_data < '12:00') & (time_data >= '11:00')].shape[0]
    time_dict['12-13'] = time_data[(time_data < '13:00') & (time_data >= '12:00')].shape[0]
    time_dict['13-14'] = time_data[(time_data < '14:00') & (time_data >= '13:00')].shape[0]
    time_dict['14-15'] = time_data[(time_data < '15:00') & (time_data >= '14:00')].shape[0]
    time_dict['15-16'] = time_data[(time_data < '16:00') & (time_data >= '15:00')].shape[0]
    # print(time_dict)
    # 垂直条形图
    # 构建数据
    GDP = list(time_dict.values())
    # 绘图
    # ax1.figure(figsize=(10, 8), dpi=80)
    # 第一个参数表示:每个柱x轴左边界,第二个参数表示:每个柱y轴下边界
    ax1.bar(range(len(GDP)), GDP, align='center', color='steelblue', alpha=0.8)
    for x, y in enumerate(GDP):
        ax1.text(x, y + 2000, '%s' % round(y, 1), ha='center', va='bottom', fontsize=12,
                 fontproperties='Times New Roman')
        break
    ax1.set_title('$\mathrm{(a)}$ 各时段流量情况', size=12, y=-0.21)  # y=-0.12
    # 轴标签
    ax1.set_xlabel('时间', {'size': 12})
    ax1.set_ylabel('流量', {'size': 12})
    # 刻度标签
    ax1.set_xticks(range(len(list(time_dict.keys()))))
    ax1.set_xticklabels(list(time_dict.keys()), fontproperties='Times New Roman', size=12)
    labels = ax1.get_xticklabels() + ax1.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = ax1.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    ax1.tick_params(labelsize=12)
    # 设置Y轴范围
    ax1.set_ylim([0, 300000])


def lower_to_capital(dict_info):
    new_dict = {}
    for i, j in dict_info.items():
        new_dict[i.upper()] = j
    return new_dict


def show_Proto():
    proto_dict = data['Proto'].value_counts().to_dict()
    new_proto_dict = {}
    other_sum = 0
    for i in proto_dict:
        if i == 'udp' or i == 'tcp' or i == 'icmp':
            new_proto_dict[i] = proto_dict.get(i)
        else:
            other_sum += proto_dict.get(i)
    new_proto_dict['others'] = other_sum
    proto_name_list = list(new_proto_dict.keys())
    for i in range(len(proto_name_list)):
        if proto_name_list[i] == 'udp' or proto_name_list[i] == 'tcp' or proto_name_list[i] == 'icmp':
            proto_name_list[i] = proto_name_list[i].upper()
        else:
            proto_name_list[i] = proto_name_list[i].capitalize()
    proto_num_list = list(new_proto_dict.values())
    temp_num = proto_num_list[3]
    proto_num_list.pop(3)
    proto_num_list.insert(1, temp_num)
    temp_name = proto_name_list[3]
    proto_name_list.pop(3)
    proto_name_list.insert(1, temp_name)
    explode = [0.05, 0.05, 0.05, 0.05]  # 用于突出圆饼图指定的一块数据,这里突出‘舞蹈’这部分
    colors = ['#9999ff', '#2442aa', '#ff9999', '#fcd300']  # 自定义颜色
    # 将横、纵坐标轴标准化处理,保证饼图是一个正圆,否则为椭圆
    ax2.pie(x=proto_num_list, labels=proto_name_list, explode=explode, autopct='%.1f%%', colors=colors,
            wedgeprops={'edgecolor': "black"}, textprops={'fontsize': 12, 'fontproperties': 'Times New Roman'},
            labeldistance=1.05)
    ax2.set_title('$\mathrm{(b)}$ 各协议占比情况', size=12, y=-0.21)  # , y=-0.12


def show_TotPkts():
    '''只展示前20[:20]'''
    totPkts_dict = data['TotPkts'].value_counts().to_dict()
    totPkts_name_list = sorted(totPkts_dict)[:20]
    # print(totPkts_name_list)
    totPkts_num_list = []
    totPkts_sum = sum(totPkts_dict.values())
    for i in totPkts_name_list:
        totPkts_num_list.append(float(format(totPkts_dict.get(i) / totPkts_sum, '.4f')))
    # 垂直条形图
    # 构建数据
    # 绘图
    # 第一个参数表示:每个柱x轴左边界,第二个参数表示:每个柱y轴下边界
    ax3.bar(range(len(totPkts_num_list)), totPkts_num_list, align='center', color='steelblue', alpha=0.8)
    ax3.set_title('$\mathrm{(c)}$ 交换的数据包总数$\mathrm{(TP)}$的频率分布情况', size=12, y=-0.21)  # , y=-0.12
    # 轴标签
    ax3.set_xlabel('数据包数量', {'size': 12})
    ax3.set_ylabel('频率', {'size': 12})
    # 刻度标签 rotation=90
    ax3.set_xticks(range(len(totPkts_name_list)))
    ax3.set_xticklabels(totPkts_name_list, fontproperties='Times New Roman', size=12)
    labels = ax3.get_xticklabels() + ax3.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = ax3.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    ax3.tick_params(labelsize=12)
    # 设置Y轴范围
    ax3.set_ylim([0, 0.6])


def show_TotBytes():
    '''只展示前20[:20]'''
    totBytes_dict = data['TotBytes'].value_counts().to_dict()
    totBytes_name_list = sorted(totBytes_dict)[:20]
    # print(totBytes_name_list)
    totBytes_num_list = []
    totBytes_sum = sum(totBytes_dict.values())
    for i in totBytes_name_list:
        totBytes_num_list.append(float(format(totBytes_dict.get(i) / totBytes_sum, '.6f')))
    # 垂直条形图
    # 构建数据
    # 绘图
    # 第一个参数表示:每个柱x轴左边界,第二个参数表示:每个柱y轴下边界
    ax4.bar(range(len(totBytes_num_list)), totBytes_num_list, align='center', color='steelblue', alpha=0.8)
    ax4.set_title('$\mathrm{(d)}$ 交换的总字节数$\mathrm{(TB)}$的频率分布情况', size=12, y=-0.21)  # , y=-0.12
    # 轴标签
    ax4.set_xlabel('总字节数', {'size': 12})
    ax4.set_ylabel('频率', {'size': 12})
    # 刻度标签 rotation=90
    ax4.set_xticks(range(len(totBytes_name_list)))
    ax4.set_xticklabels(totBytes_name_list, fontproperties='Times New Roman', size=12)
    labels = ax4.get_xticklabels() + ax4.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = ax4.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    ax4.tick_params(labelsize=12)
    # 设置Y轴范围
    ax4.set_ylim([0, 0.005])


def show_SrcBytes():
    '''只展示前20[:20]'''
    srcBytes_dict = data['SrcBytes'].value_counts().to_dict()
    srcBytes_name_list = sorted(srcBytes_dict)[:20]
    # print(srcBytes_name_list)
    srcBytes_num_list = []
    srcBytes_sum = sum(srcBytes_dict.values())
    for i in srcBytes_name_list:
        srcBytes_num_list.append(float(format(srcBytes_dict.get(i) / srcBytes_sum, '.6f')))
    # 垂直条形图
    # 构建数据
    # 绘图
    # 第一个参数表示:每个柱x轴左边界,第二个参数表示:每个柱y轴下边界
    ax5.bar(range(len(srcBytes_num_list)), srcBytes_num_list, align='center', color='steelblue', alpha=0.8)
    ax5.set_title('$\mathrm{(e)}$ 源头发送的字节数$\mathrm{(SB)}$的频率分布情况', size=12, y=-0.21)
    # 轴标签
    ax5.set_xlabel('源字节数', {'size': 12})
    ax5.set_ylabel('频率', {'size': 12})
    # 刻度标签 rotation=90
    ax5.set_xticks(range(len(srcBytes_name_list)))
    ax5.set_xticklabels(srcBytes_name_list, fontproperties='Times New Roman', size=12)
    labels = ax5.get_xticklabels() + ax5.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = ax5.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    ax5.tick_params(labelsize=12)
    # 设置Y轴范围
    ax5.set_ylim([0, 0.04])


def show_label():
    label_data = data['Label'].tolist()
    num_sum = len(label_data)
    num_Background = 0
    num_To_Background = 0
    num_From_Normal = 0
    num_From_Background = 0
    num_From_Botnet = 0
    num_To_Normal = 0
    num_Normal = 0
    for i in label_data:
        if i.startswith('flow=Background'):
            num_Background += 1
        if i.startswith('flow=To-Background'):
            num_To_Background += 1
        if i.startswith('flow=From-Normal'):
            num_From_Normal += 1
        if i.startswith('flow=From-Background'):
            num_From_Background += 1
        if i.startswith('flow=From-Botnet'):
            num_From_Botnet += 1
        if i.startswith('flow=To-Normal'):
            num_To_Normal += 1
        if i.startswith('flow=Normal'):
            num_Normal += 1

    # print(num_Background, num_To_Background, num_From_Normal, num_From_Background, num_From_Botnet,
    #       num_To_Normal, num_Normal)
    label_name_list = ['BG', 'FBG', 'TBG', 'N', 'FN', 'TN',
                       'FBot']
    label_num_list = []
    label_num_list.append(float(format(num_Background / num_sum, '.6f')))
    label_num_list.append(float(format(num_From_Background / num_sum, '.6f')))
    label_num_list.append(float(format(num_To_Background / num_sum, '.6f')))
    label_num_list.append(float(format(num_Normal / num_sum, '.6f')))
    label_num_list.append(float(format(num_From_Normal / num_sum, '.6f')))
    label_num_list.append(float(format(num_To_Normal / num_sum, '.6f')))
    label_num_list.append(float(format(num_From_Botnet / num_sum, '.6f')))
    # 垂直条形图
    # 构建数据
    # 绘图
    # 第一个参数表示:每个柱x轴左边界,第二个参数表示:每个柱y轴下边界
    ax6.bar(range(len(label_num_list)), label_num_list, align='center', color='steelblue', alpha=0.8)
    ax6.set_title('$\mathrm{(f)}$ 标签频率分布情况', size=12, y=-0.21)
    # 轴标签
    ax6.set_xlabel('标签类别', {'size': 12})
    ax6.set_ylabel('频率', {'size': 12})
    # 刻度标签 rotation=90
    ax6.set_xticks(range(len(label_name_list)))
    ax6.set_xticklabels(label_name_list, fontproperties='Times New Roman', size=12)
    labels = ax6.get_xticklabels() + ax6.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = ax6.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    ax6.tick_params(labelsize=12)
    # 设置Y轴范围
    ax6.set_ylim([0, 0.6])
    # 为每个条形图添加数值标签
    flag = 0
    for x, y in enumerate(label_num_list):
        if flag == 1 or flag == 3 or flag == 5 or flag == 6:
            ax6.text(x, y + 0.002, '%.3f%%' % (round(float(y), 6) * 100), ha='center', va='bottom', fontsize=12,
                     fontproperties='Times New Roman')
        flag += 1
    ax6.legend(labels=[
        '$\mathrm{BG:Background}$\n$\mathrm{FBG:From_-Background}$\n$\mathrm{TBG:To_-Background}$\n$\mathrm{N:Normal}$\n$\mathrm{FN:From_-Normal}$\n$\mathrm{TN:To_-Normal}$\n$\mathrm{FBOT:From_-Botnet}$'],
        loc='best', fontsize=12)


if __name__ == '__main__':
    show_StartTime()
    show_Proto()
    show_TotPkts()
    show_TotBytes()
    show_SrcBytes()
    show_label()
    plt.savefig( '组合图.svg', bbox_inches='tight', pad_inches=0)
    # plt.savefig('组合图.png', bbox_inches='tight', pad_inches=0, dpi=1200)
    plt.show()

在这里插入图片描述

(3)堆积柱状图

# 代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
# 部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
# 感谢在我科研绘图过程中提供帮助的各位博主!

# 导包
import matplotlib.pyplot as plt
from matplotlib import rcParams
# 设置配置文件
config = {
# 衬线字体(衬线字体, 宋体和Times New Roman属于这类字体)
    "font.family": 'serif',
    # matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
    "mathtext.fontset": 'stix',
    # 设置绘图时全局字体为宋体(SimSun)
    "font.serif": ['SimSun'],
}
# 修改运行时配置参数的方法(Matplotlib使用matplotlibrc配置文件来自定义图形的各种属性,称之为rc配置或rc参数(rcParams))
rcParams.update(config)

# 我研究时用到的数据
time_windows = [5, 10, 15, 20, 30, 60, 90, 120, 240, 480, 960, 1200, 1800]
pos_num = [86403, 74801, 69846, 66853, 63407, 58035, 55143, 53161, 48644, 43749, 39254, 38063, 35942]
neg_num = [976352, 946428, 930373, 919305, 905210, 880228, 862600, 850607, 821876, 792561, 763754, 754271, 738900]
plt.figure(figsize=(8, 3))
# 绘制柱状图
plt.bar(range(len(time_windows)), list(map(int, pos_num)), label='正样本')
# bottom:柱状图底部离横轴的距离
plt.bar(range(len(time_windows)), list(map(int, neg_num)), label='负样本', bottom=list(map(int, pos_num)))
# 设置x轴刻度值、字体类型、字号
plt.xticks(range(len(time_windows)), time_windows, fontname='Times New Roman', size=12)
# 设置y轴刻度字体类型、字号
plt.yticks(fontname='Times New Roman', size=12)
# 设置xy轴标题和字号
plt.xlabel('时间窗口$\mathrm{(}$秒$\mathrm{)}$', {'size': 12})
plt.ylabel('样本数', {'size': 12})
# 设置科学计数法字体字号
plt.gca().yaxis.get_offset_text().set(size=12, fontproperties='Times New Roman')
# 设置图例,framealpha: 控制图例框的透明度,frameon:是否显示图例边框,ncol: 图例的列的数量,默认为1,handlelength: 图例句柄的长度,
# labelspacing: 图例中条目之间的距离,loc:图例位置,可取(‘best’, ‘upper right’, ‘upper left’, ‘lower left’, ‘lower right’, ‘right’,
# ‘center left’, ‘center , right’, ‘lower center’, ‘upper center’, ‘center’) ,bbox_to_anchor: (横向看右,纵向看下),
# 如果要自定义图例位置或者将图例画在坐标外边,用它,比如bbox_to_anchor=(1.4, 0.8)
plt.legend(fontsize=12, framealpha=0.2, ncol=1, loc='upper right',
           columnspacing=0.5,
           handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False)
# 设置数据显示格式为科学计数法,scilimits=(0, 0)表示不限制科学计数法的位数,也就是说无论数字大小如何,都会以科学计数法显示。
plt.ticklabel_format(style='sci', scilimits=(0, 0), axis='y')
plt.savefig('./堆积柱状图.svg', bbox_inches='tight', pad_inches=0)
# plt.savefig('./堆积柱状图.png', bbox_inches='tight', pad_inches=0,dpi=1200)
plt.show()

在这里插入图片描述

(4)混淆矩阵

# 此部分代码仅截取了部分内容,仅供参考
import pandas as pd
import os
from sklearn.model_selection import train_test_split
import joblib
from sklearn import tree
from sklearn.metrics import accuracy_score
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score
from sklearn.metrics import f1_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import matthews_corrcoef  # 计算MCC
from sklearn.metrics import roc_auc_score  # 计算MCC 只对二分类可以计算
from sklearn.ensemble import AdaBoostClassifier
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from sklearn.naive_bayes import MultinomialNB, GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
from matplotlib import rcParams
import seaborn as sns
from lightgbm.sklearn import LGBMClassifier
from catboost import CatBoostClassifier

ctu_13_list = [4, 9]
time_windows = [5, 10, 15, 20, 30, 60, 90, 120, 240, 480, 960, 1200, 1800]
file_suffix = ['new_capture20110815.binetflow', 'new_capture20110817.binetflow']
config = {
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
}
rcParams.update(config)
sns.set()
sns.set_style({'font.sans-serif': ['Times New Roman']})


def show_acc_pre_rec_f1_mcc_auc(method_name, y_test, predictions):
    print(method_name, "准确率accuracy_score:%.2f%%" % (accuracy_score(y_test, predictions) * 100), end=', ')
    print("召回率recall_score:%.2f%%" % (recall_score(y_test, predictions, pos_label=1) * 100), end=', ')
    print("精确率precision_score:%.2f%%" % (precision_score(y_test, predictions, pos_label=1) * 100), end=', ')
    print("F1值f1_score:%.2f%%" % (f1_score(y_test, predictions, pos_label=1) * 100), end=', ')
    print("MCC:%.2f%%" % (matthews_corrcoef(y_test, predictions) * 100), end=', ')
    print("AUC:%.2f%%" % (roc_auc_score(y_test, predictions) * 100))


# 通过热力图显示混淆矩阵
def show_confusion_matrix(id, time_win, method_name, labels, predictions):
    file_location = os.getcwd() + '\\CTU-13\\' + str(id) + '\\' + str(time_win)
    f, ax = plt.subplots()
    C2 = confusion_matrix(labels, predictions, labels=[0, 1])
    # print(C2)  # 打印出来看看
    h = sns.heatmap(C2, annot=True, fmt="d", ax=ax, cbar=False)  # 画热力图
    # ax.text(fontsize=12, fontname='Times New Roman')
    ax.set_title('CTU-13-' + str(id) + '\n(time_win=' + str(time_win) + 's, clf=' + method_name + ')',
                 fontproperties='Times New Roman', fontsize=12)  # 标题
    ax.set_xlabel('预测值', fontproperties='SimSun', size=12)  # x轴
    ax.set_ylabel('真实值', fontproperties='SimSun', size=12)  # y轴
    ax.set_xticklabels([0, 1], fontproperties='Times New Roman', size=12)
    ax.set_yticklabels([0, 1], fontproperties='Times New Roman', size=12)
    # 设置色彩盘字体大小
    cbar = h.figure.colorbar(h.collections[0])
    cbar.ax.tick_params(labelsize=12)
    # 修改色彩盘中字体
    cbarlabels = cbar.ax.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in cbarlabels]
    plt.savefig(file_location + '\\使用' + method_name + '方法的混淆矩阵.svg')
    # plt.show()


def default_model_eva(id, filePath, time_win):
    model_save_path = os.getcwd() + '\\CTU-13\\' + str(id) + '\\' + str(time_win)
    data = pd.read_csv(filePath, index_col=None)
    # print(data.columns)
    X = data.drop(['Label'], axis=1)
    y = data['Label']
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    # GaussianNB
    gnb = GaussianNB()  # 使用默认配置初始化朴素贝叶斯
    gnb.fit(X_train, y_train)  # 利用训练数据对模型参数进行估计
    joblib.dump(gnb, model_save_path + '\\GaussianNB.pkl', compress=3)
    predictions = gnb.predict(X_test)  # 对参数进行预测
    show_acc_pre_rec_f1_mcc_auc('GaussianNB', y_test, predictions)
    show_confusion_matrix(id, time_win, 'GaussianNB', y_test, predictions)

在这里插入图片描述

(5)局部放大+图中注释+折线图

import pandas as pd
import os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from mpl_toolkits.axes_grid1.inset_locator import TransformedBbox, BboxPatch, BboxConnector

config = {  # SimSun
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
}
rcParams.update(config)
time_windows = [5, 10, 15, 20, 30, 60, 90, 120, 240, 480, 960, 1200, 1800]
pic_model_name_list = ['FS-GLE$^{[56]+[57]}$',
                       'CRITIC-GLE$^{[62]+[57]}$',
                       'EW-CLE$^{[66]+[57]}$',
                       'CWOA-CLE$^{[79]+[57]}$',
                       'CRITIC-SFS$^{[62]+[59]}$',
                       'SBS$^{[60]}$',
                       'RFE$^{[61]}$',
                       'MADM-ARC-SFS']
color_list = ['#99cc00', '#00994e', '#800080', '#df3881', '#00a8e1', '#e30039', '#9c9800', '#0000ff']  # f19272 0000ff
marker_list = ['p', '*', 'o', 'v', 's', 'd', 'h', 'X']
markersize_list = [10, 10, 8, 8, 8, 8, 8, 8]
data = [[0.8505, 0.8712, 0.8756, 0.8876, 0.8878, 0.8981, 0.9104, 0.9177, 0.9306, 0.9371, 0.9488, 0.9459, 0.9547],
        [0.8518, 0.8856, 0.8913, 0.8979, 0.8941, 0.9037, 0.9128, 0.9158, 0.9363, 0.9368, 0.9499, 0.9529, 0.9504],
        [0.8502, 0.873, 0.8849, 0.8934, 0.8954, 0.9026, 0.9142, 0.9216, 0.935, 0.9409, 0.9495, 0.9543, 0.95],
        [0.8514, 0.882, 0.8909, 0.8939, 0.8949, 0.9057, 0.9153, 0.9216, 0.9349, 0.9431, 0.9495, 0.9546, 0.9527],
        [0.8585, 0.8814, 0.889, 0.8893, 0.8941, 0.9066, 0.9146, 0.9191, 0.9313, 0.94, 0.9452, 0.9489, 0.9496],
        [0.8544, 0.8765, 0.8857, 0.8928, 0.8957, 0.9086, 0.9169, 0.9172, 0.9292, 0.936, 0.9435, 0.9461, 0.9456],
        [0.8494, 0.8717, 0.8793, 0.8853, 0.8899, 0.9028, 0.9146, 0.9207, 0.9329, 0.9411, 0.948, 0.9513, 0.9509],
        [0.8675, 0.8937, 0.9, 0.9008, 0.9014, 0.9183, 0.9244, 0.9251, 0.9409, 0.9454, 0.9548, 0.9578, 0.9554]]
feature_num = [18, 11, 10, 12, 13, 10, 9, 13, 13, 13, 11, 9, 13]


def mark_inset(parent_axes, inset_axes, loc1a=1, loc1b=1, loc2a=2, loc2b=2, **kwargs):
    rect = TransformedBbox(inset_axes.viewLim, parent_axes.transData)

    pp = BboxPatch(rect, fill=False, **kwargs)
    parent_axes.add_patch(pp)

    p1 = BboxConnector(inset_axes.bbox, rect, loc1=loc1a, loc2=loc1b, **kwargs)
    inset_axes.add_patch(p1)
    p1.set_clip_on(False)
    p2 = BboxConnector(inset_axes.bbox, rect, loc1=loc2a, loc2=loc2b, **kwargs)
    inset_axes.add_patch(p2)
    p2.set_clip_on(False)

    return pp, p1, p2


def compare_MCC():
    fig, ax1 = plt.subplots()
    for i in range(len(data)):
        ax1.plot(range(len(time_windows)), data[i], color=color_list[i],
                 marker=marker_list[i], markersize=markersize_list[i],
                 linewidth=1.0, markerfacecolor='none')
        if i == len(data) - 1:
            num = 0
            for a, b in zip(range(len(time_windows)), data[i]):
                ax1.text(a, b + 0.002, "(" + str('%.0f' % feature_num[num]) + ")", ha='center', va='bottom', fontsize=9,
                         fontproperties='Times New Roman')
                num += 1
    ax1.set_xticks(range(len(time_windows)))
    ax1.set_xticklabels(time_windows, fontproperties='Times New Roman', size=12)
    labels = ax1.get_xticklabels() + ax1.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = ax1.get_xticklabels() + ax1.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    ax1.set_ylim([0.84, 0.965])
    ax1.set_xlabel('时间窗口$\mathrm{(}$秒$\mathrm{)}$', {'size': 12})
    ax1.set_ylabel('$\mathrm{\it MCC}$', {'size': 12})
    ax1.annotate("本文算法最优\n特征子集特征数", xy=(6, 0.93), xycoords='data',
                 bbox=dict(boxstyle="round", fc="none", ec="gray"),
                 xytext=(6, 0.945), ha='center',
                 arrowprops=dict(arrowstyle="->"))
    axins = ax1.inset_axes((0.64, 0.02, 0.36, 0.66))
    for i in range(len(data)):
        axins.plot(range(8, len(time_windows)), data[i][8:], color=color_list[i],
                   marker=marker_list[i],
                   markersize=markersize_list[i],
                   linewidth=1.0, markerfacecolor='none')
    axins.set_xticks([])
    # axins.set_xticklabels(time_windows[8:], fontproperties='Times New Roman', size=12)
    axins.set_ylim([0.93, 0.96])
    axins.yaxis.set_label_position("right")
    axins.yaxis.tick_right()
    labels = axins.get_xticklabels() + axins.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = axins.get_xticklabels() + axins.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    axins.annotate("$\mathrm{240}$-$\mathrm{1800}$", xy=(11.2, 0.931), xycoords='data',
                   xytext=(11.2, 0.931), ha='center', size=12)
    # for key, spine in axins.spines.items():
    #     # 'left', 'right', 'bottom', 'top'
    #     if key == 'left' or key == 'top':
    #         spine.set_visible(False)
    # loc1 loc2: 坐标系的四个角
    # 1 (右上) 2 (左上) 3(左下) 4(右下)
    mark_inset(ax1, axins, loc1a=1, loc1b=4, loc2a=2, loc2b=3, fc='none', ec='gray', linestyle='--')
    axins2 = ax1.inset_axes((0.325, 0.02, 0.3, 0.34))
    for i in range(len(data)):
        axins2.plot(range(5, 7), data[i][5:7], color=color_list[i],
                    marker=marker_list[i],
                    markersize=markersize_list[i],
                    linewidth=1.0, markerfacecolor='none')
    axins2.set_xticks([])
    axins2.set_ylim([0.901, 0.917])
    labels = axins2.get_xticklabels() + axins2.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    y_labels = axins2.get_yticklabels()
    [label.set_fontsize(12) for label in y_labels]
    axins2.annotate("$\mathrm{30}$-$\mathrm{60}$", xy=(5.8, 0.902), xycoords='data',
                    xytext=(5.8, 0.902), ha='center', size=12)
    mark_inset(ax1, axins2, loc1a=1, loc1b=4, loc2a=2, loc2b=3, fc='none', ec='gray', linestyle='--')
    labelss = plt.legend(labels=pic_model_name_list, fontsize=12, framealpha=0.2, ncol=1, loc='upper left',
                         columnspacing=0.5,
                         handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False).get_texts()
    [label.set_fontname('Times New Roman') for label in labelss]
    label = labelss[-1]
    label.set_fontweight('bold')
    plt.savefig('./局部放大+图中注释+折线图.svg', bbox_inches='tight', pad_inches=0)
    # plt.savefig('./局部放大+图中注释+折线图.png', bbox_inches='tight', pad_inches=0,dpi=1200)
    plt.show()


if __name__ == '__main__':
    compare_MCC()

在这里插入图片描述

(6)糖葫芦图

# 代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
# 部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
# 感谢在我科研绘图过程中提供帮助的各位博主!

# 导包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams

# 设置配置文件
config = {
    # 衬线字体(衬线字体, 宋体和Times New Roman属于这类字体)
    "font.family": 'serif',
    # matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
    "mathtext.fontset": 'stix',
    # 设置绘图时全局字体为宋体(SimSun)
    "font.serif": ['SimSun'],
}
# 修改运行时配置参数的方法(Matplotlib使用matplotlibrc配置文件来自定义图形的各种属性,称之为rc配置或rc参数(rcParams))
rcParams.update(config)
# 糖葫芦图图例,在我的研究中是指基准测试函数
fun_name = ["$\mathrm{\itf_1}$", "$\mathrm{\itf_2}$", "$\mathrm{\itf_3}$", "$\mathrm{\itf_4}$",
            "$\mathrm{\itf_5}$", "$\mathrm{\itf_6}$", "$\mathrm{\itf_7}$", "$\mathrm{\itf_8}$"]
# 糖葫芦图x轴坐标刻度所显示的内容
method_name = ['$\mathrm{BES}$', '$\mathrm{BES1}$', '$\mathrm{BES2}$',
               '$\mathrm{BES3}$', '$\mathrm{BES4}$',
               '$\mathrm{BES5}$', '$\mathrm{BES6}$', '$\mathrm{BES7}$',
               '$\mathrm{BES8}$', '$\mathrm{BES9}$',
               '$\mathrm{ICBES}$']
# 为每个图例提供颜色,颜色顺序与method_name顺序对应
color_list = ['#00a8e1', '#99cc00', '#00994e', '#ff6600', '#0000ff', '#800080', '#e30039', '#db00c2', '#555555',
              '#f47a75', '#9c9800', '#76da91']
# 设置marker
marker_list = ['s', 'p', '*', 'P', 'X', 'o', '^', 'H', 'v', 'd', 'h', 'D']
# 设置marker大小
markersize_list = [8, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 8]
# 读取数据文件,数据与数据之间的分隔符为制表符(Tab键)
data = pd.read_csv('糖葫芦图数据.txt', sep='\t')
results = []
# 按列检索
for i in data.columns:
    # 按method_name顺序检索数据中的每一类存入results
    results.append(data[i].tolist())
####
# “####”之间的代码是我研究中需要的
# 计算method_name中每类的均值
avg_list = list(np.average(np.array(results), axis=1))
# 按照均值大小排序
sorted_avg_list = sorted(avg_list)
# 确定排序序号
index_avg_list = []
for i in avg_list:
    index_avg_list.append(str(int(sorted_avg_list.index(i) + 1)))
final_results = list(np.array(results).T)
# 存放没类最大序列序号
height_list = []
for i in range(len(results)):
    height_list.append(np.max(results[i]))
####
# 创建子图,设置图片(width, height)
fig, ax1 = plt.subplots(figsize=(8, 3))
line_label = []
# 糖葫芦图就是折线图的变体,先绘制折线图,然后隐去折现,用竖线将同类连接
for i in range(data.shape[0]):
    # range(len(method_name))横坐标的值,final_results[i]纵坐标的值,color:折线图的颜色,marker:折线图的点的形状,
    # linestyle:折线图的线的样式,linewidth:折线图的线的宽度,markerfacecolor标记内部的颜色
    line1, = ax1.plot(range(len(method_name)), final_results[i], color=color_list[i],
                      marker=marker_list[i], markersize=markersize_list[i],
                      linewidth=1.0, markerfacecolor='none', linestyle='')
    line_label.append(line1)
# x=range(len(method_name))处开始绘制竖线,竖线起始位置ymin,竖线终止位置ymax,透明度alpha,线粗细linewidth
ax1.vlines(range(len(method_name)), ymin=0, ymax=height_list, alpha=0.7, linewidth=0.5)
# 设置x轴和y轴刻度
ax1.set_xticks([])
ax1.set_yticks(range(12))
# 获取y轴label对象
labels = ax1.get_yticklabels()
# 修改y轴label字体类型
[label.set_fontname('Times New Roman') for label in labels]
y_labels = ax1.get_yticklabels()
# 修改y轴label字号
[label.set_fontsize(12) for label in y_labels]
# 修改y轴图例字号
ax1.set_ylabel('排名', {'size': 12})
# 设置y轴刻度显示范围
ax1.set_ylim([0.5, 11.5])
columns = (
    'BES', 'BES1', 'BES2', 'BES3', 'BES4', 'BES5', 'BES6', 'BES7', 'BES8', 'BES9', 'ICBES')
rows = ['排名均值', '排名均值排序']
fianl_avg_list = []
# 设置显示的数值保留三位小数
for i in avg_list:
    fianl_avg_list.append(format(i, '.3f'))
pd_data = [fianl_avg_list, index_avg_list]
pltPD = pd.DataFrame(pd_data, columns=columns, index=rows)
# 柱状图添加table数据表
# cellText:表格单元格文本,字符串中的换行符暂不支持,可能导致文本超出单元格边界
# cellColours:表格单元格背景色
# cellLoc:表格单元格文本的对齐方式,取值范围为{'left', 'center', 'right'},默认值为'right'
# colWidths:表格单元格宽度
# rowLabels:表格行表头文本
# rowColours:表格行表头背景色
# rowLoc:表格行表头文本的对齐方式,取值范围为{'full', 'left', 'right'},默认值为'left'
# colLabels:表格列表头文本
# colColours:表格列表头背景色
# colLoc:表格列表头文本的对齐方式,取值范围为{'full', 'left', 'right'},默认值为'left'
# loc:单元格相对于子图的位置
# bbox:绘制表格的边界框
the_table = plt.table(cellText=pltPD.values, rowLabels=pltPD.index.values,
                      colLabels=pltPD.columns.values,
                      loc='bottom', cellLoc='center', rowLoc='center')
# 设置图表table单元格文本字体
the_table.auto_set_font_size(False)
the_table.set_fontsize(12)
for (row, col), cell in the_table.get_celld().items():
    if col != -1:
        cell.set_text_props(fontproperties='Times New Roman', size=12)
        if row == 0 and col == 10:
            cell.set_text_props(weight='bold')
        if row == 2:
            cur_text = cell.get_text().get_text()
            if cur_text == '1':
                cell.set_text_props(weight='bold')
# 设置图例,framealpha: 控制图例框的透明度,frameon:是否显示图例边框,ncol: 图例的列的数量,默认为1,handlelength: 图例句柄的长度,
# labelspacing: 图例中条目之间的距离,loc:图例位置,可取(‘best’, ‘upper right’, ‘upper left’, ‘lower left’, ‘lower right’, ‘right’,
# ‘center left’, ‘center , right’, ‘lower center’, ‘upper center’, ‘center’) ,bbox_to_anchor: (横向看右,纵向看下),
# 如果要自定义图例位置或者将图例画在坐标外边,用它,比如bbox_to_anchor=(1.4, 0.8)
ax1.legend((line_label[0], line_label[1], line_label[2], line_label[3], line_label[4], line_label[5], line_label[6],
            line_label[7]), fun_name, fontsize=12, framealpha=0.2, bbox_to_anchor=(-0.65, 0.65, 1, 0.2),
           loc='upper center', ncol=1, columnspacing=0.5,
           handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False)
# 存储为SVG格式(矢量图不失真),bbox_inches='tight', pad_inches=0可以去除图片的白边
# plt.savefig('糖葫芦图.svg', bbox_inches='tight', pad_inches=0)
plt.savefig('糖葫芦图.png', bbox_inches='tight', pad_inches=0, dpi=1200)
plt.show()

在这里插入图片描述

(7)横向柱状图+折线图

import os
import matplotlib.pyplot as plt
from matplotlib import rcParams

config = {  # SimSun
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
}
rcParams.update(config)

pic_model_name_list = ['$\mathrm{EW}$-$\mathrm{GLE^{[41]+[34]}}$',
                       '$\mathrm{CWOA}$-$\mathrm{GLE^{[38]+[34]}}$', '$\mathrm{FS}$-$\mathrm{CLE^{[39]+[34]}}$',
                       '$\mathrm{CVCRITIC}$-$\mathrm{SFS^{[37]}}$', '$\mathrm{SBS^{[49]}}$',
                       '$\mathrm{RFE^{[35]}}$',
                       '$\mathrm{MARC}$-$mathrm{ARC}$-$\mathrm{SFS}$(本文)']
model_name_list = ['EW-GLE', 'CWOA-GLE', 'FS-CLE', 'CVCRITIC-SFS', 'SBS', 'RFE', 'MARC-ARC-SFS']
literature_pic_weight = [0, 3, 6, 9, 12, 15, 18]
mean_list = [0.9647, 0.9426, 0.9579, 0.955, 0.9511, 0.8619, 0.8356]
cv_list = [0.0155, 0.0228, 0.0172, 0.0156, 0.0134, 0.1172, 0.1262]
# 逆置
model_name_list.reverse()
fig, ax1 = plt.subplots()
ax2 = ax1.twiny()
line1 = ax1.barh(range(len(literature_pic_weight)), mean_list, color='#9ecae1',
                 height=0.8)
line2, = ax2.plot(cv_list, range(len(literature_pic_weight)), color='black', marker='o', markersize=4,
                 linewidth=2, linestyle=':')
ax1.set_yticks(range(len(literature_pic_weight)))
ax2.set_yticklabels([])
ax1.set_yticklabels(model_name_list, size=12)
ax1.set_xlim([0.82, 0.97])
ax2.set_xlim([0.01, 0.13])
labels = ax1.get_xticklabels() + ax1.get_yticklabels() + ax2.get_xticklabels()
[label.set_fontname('Times New Roman') for label in labels]
labels = ax1.get_xticklabels() + ax1.get_yticklabels() + ax2.get_xticklabels()
[label.set_fontsize(12) for label in labels]
ax1.get_yticklabels()[0].set_fontweight('bold')
ax1.set_xlabel(r'$\mathrm{\it\overline{MCC}}$', {'size': 12})
ax1.set_ylabel('不同特征选择算法', {'size': 12})
ax2.set_xlabel('$\mathrm{\it{CV}}$', {'size': 12})
num = 0
for a, b in zip(range(len(literature_pic_weight)), mean_list):
    if num == 0:
        ax1.text(b - 0.007, a, str('%.4f' % b), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman', fontweight='bold')
    else:
        ax1.text(b - 0.007, a, str('%.4f' % b), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    num += 1
num=0
for a, b in zip(range(len(literature_pic_weight)), cv_list):
    if num == 4:
        ax2.text(b+0.0025, a + 0.2, str('%.4f' % b), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman', fontweight='bold')
    elif num == len(cv_list)-1:
        ax2.text(b-0.002, a + 0.2, str('%.4f' % b), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    else:
        ax2.text(b+0.001, a + 0.2, str('%.4f' % b), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    num += 1
plt.legend([line1,line2],[r'$\mathrm{\it\overline{MCC}}$','$\mathrm{\it{CV}}$'], fontsize=12, framealpha=0.2, ncol=2, loc='upper center',
                         columnspacing=0.5,
                         handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False)
plt.savefig('./横向柱状图+折线图.svg', bbox_inches='tight', pad_inches=0)
# plt.savefig('./横向柱状图+折线图.png', bbox_inches='tight', pad_inches=0,dpi=1200)
plt.show()

在这里插入图片描述

(8)雷达图

# 代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
# 部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
# 感谢在我科研绘图过程中提供帮助的各位博主!

# 导包
# coding=utf-8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import rcParams

# 设置配置文件
config = {
    # 衬线字体(衬线字体, 宋体和Times New Roman属于这类字体)
    "font.family": 'serif',
    # matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
    "mathtext.fontset": 'stix',
    # 设置绘图时全局字体为宋体(SimSun)
    "font.serif": ['SimSun'],
}
# 修改运行时配置参数的方法(Matplotlib使用matplotlibrc配置文件来自定义图形的各种属性,称之为rc配置或rc参数(rcParams))
rcParams.update(config)
# 雷达图每个角的数值,在我的研究中是指基准测试函数
fun_name = ["$\mathrm{\itf_1}$", "$\mathrm{\itf_2}$", "$\mathrm{\itf_3}$", "$\mathrm{\itf_4}$",
            "$\mathrm{\itf_5}$", "$\mathrm{\itf_6}$", "$\mathrm{\itf_7}$", "$\mathrm{\itf_8}$"]
# 图例内容
method_name = ['$\mathrm{BES}$', '$\mathrm{BES1}$', '$\mathrm{BES2}$',
               '$\mathrm{BES3}$', '$\mathrm{BES4}$',
               '$\mathrm{BES5}$', '$\mathrm{BES6}$', '$\mathrm{BES7}$',
               '$\mathrm{BES8}$', '$\mathrm{BES9}$',
               '$\mathrm{ICBES}$']
# 为每个扇形提供颜色,颜色顺序与method_name顺序对应
color_list = ['#00a8e1', '#99cc00', '#00994e', '#ff6600', '#800080', '#e30039', '#db00c2', '#555555', '#f47a75',
              '#9c9800', '#0000ff']
# 设置marker
marker_list = ['s', 'p', '*', 'P', 'o', '^', 'H', 'v', 'd', 'h', 'X']
# 设置marker大小
markersize_list = [6, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6]
# 读取数据文件,数据与数据之间的分隔符为制表符(Tab键)
data = pd.read_csv('./雷达图数据.txt', sep='\t')
results = []
# 按列检索
for i in data.columns:
    # 将两个list列表对象转为dict字典对象,存入results
    results.append(dict(zip(fun_name, data[i].tolist())))
# 记录单条数据长度
data_length = len(results[0])
# 将极坐标根据数据长度进行等分
# 作为序列生成器, np.linspace()函数用于在线性空间中以均匀步长生成数字序列。这里使用序列生成器,均匀生成雷达图中每个点相对于极轴的角度(弧度制)。
# 从0到2π正好一圈,数据个数为data_length,endpoint=True表示是包含终止值(默认),endpoint=False表示不包含终止值
angles = np.linspace(0, 2 * np.pi, data_length, endpoint=False)
# 读取每一个fun_name下对应的数据
score = [[v for v in result.values()] for result in results]
# 使雷达图数据封闭
# np.concatenate((angles, [angles[0]]))按照先angles后[angles[0]]顺序将两个list拼接
angles = np.concatenate((angles, [angles[0]]))
labels = np.concatenate((fun_name, [fun_name[0]]))
# 新建一个子图 polar表示一个极点图
ax = plt.subplot(111, polar=True)
# 绘制雷达图
for i in range(len(results)):
    score_a = np.concatenate((score[i], [score[i][0]]))
    ax.plot(angles, score_a, color=color_list[i], lw=1, marker=marker_list[i],
            markersize=markersize_list[i])
# 设置雷达图中每一项的标签显示
ax.set_thetagrids(angles * 180 / np.pi, labels)
# 设置雷达图的0度起始位置
ax.set_theta_zero_location('N')  # E W S N SW SE NW NE
# 设置雷达图的坐标刻度范围
ax.set_rlim(0, 11)
# 设置雷达图的坐标值显示角度,相当于y起始角度的偏移量
ax.set_rlabel_position(270)
# 获取x和y轴label对象
labels = ax.get_xticklabels() + ax.get_yticklabels()
# 修改坐标轴label字体类型
[label.set_fontname('Times New Roman') for label in labels]
y_labels = ax.get_xticklabels() + ax.get_yticklabels()
# 修改坐标轴label字号
[label.set_fontsize(12) for label in y_labels]
# 设置图例,framealpha: 控制图例框的透明度,frameon:是否显示图例边框,ncol: 图例的列的数量,默认为1,handlelength: 图例句柄的长度,
# labelspacing: 图例中条目之间的距离,loc:图例位置,可取(‘best’, ‘upper right’, ‘upper left’, ‘lower left’, ‘lower right’, ‘right’,
# ‘center left’, ‘center , right’, ‘lower center’, ‘upper center’, ‘center’) ,bbox_to_anchor: (横向看右,纵向看下),
# 如果要自定义图例位置或者将图例画在坐标外边,用它,比如bbox_to_anchor=(1.4, 0.8)
plt.legend(method_name, fontsize=12, framealpha=0.2, bbox_to_anchor=(0.7, 0.65, 1, 0.2),
           loc='upper center', ncol=1, columnspacing=0.5,
           handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False)
ax.fill(angles, np.concatenate((score[10], [score[10][0]])), facecolor=color_list[10], alpha=0.1)
# 存储为SVG格式(矢量图不失真),bbox_inches='tight', pad_inches=0可以去除图片的白边
# plt.savefig('雷达图.svg', bbox_inches='tight', pad_inches=0)
plt.savefig('雷达图.png', bbox_inches='tight', pad_inches=0, dpi=1200)
plt.show()

在这里插入图片描述
我在使用matplotlib绘制雷达图并将图片保存为svg时,f3显示不全。可以通过Inkscape(https://inkscape.org/zh-hant/)编辑SVG,调整SVG图像位置。
在这里插入图片描述

(9)多组柱状图

# coding=utf-8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.pyplot import MultipleLocator

config = {  # SimSun
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
}
rcParams.update(config)
fun_name = ['重采样样本', 'GLE', 'CLE', 'SFS', 'SBS', 'RFE', 'MADM-ARC-SFS']
# fun_name = ["$\mathrm{\itAcc}$", "$\mathrm{\itPre}$", "$\mathrm{\itRec}$", "$\mathrm{\itF-score}$",
#             "$\mathrm{\itMCC}$", "$\mathrm{\itSpe}$", "$\mathrm{\itGM}$", "$\mathrm{\itYI}$"]
method_name = ['场景$\mathrm{4\;\itN^{\Phi_{\mathrm{best}}}}$', '场景$\mathrm{4\;\itDRR}$', '场景$\mathrm{9\;\itN^{\Phi_{\mathrm{best}}}}$', '场景$\mathrm{9\;\itDRR}$']
color_list = ['#FFB3B3', '#FFDBA4', '#F7F6DC', '#C1EFFF']  # 原配色['#ceefe4','#5BE7C4','#50C1E9','#7A57D1']
literature_pic_weight = [0,4,8,12,16,20,24]
# patterns_list = ['.', 'o']
data = pd.read_csv('./多组柱状图.txt', sep='\t')
results = []
for i in data.index:
    results.append(data.loc[i].values[0:].tolist())
fig, axBF = plt.subplots(figsize=(8, 3))
axDRR = axBF.twinx()
b = [i - 1.2 for i in literature_pic_weight]
lineAcc_1 = axBF.bar(b, [int(results[0][0]), int(results[1][0]), int(results[2][0]), int(results[3][0]),
                         int(results[4][0]), int(results[5][0]), int(results[6][0])], color=color_list[0], width=0.8,
                     )
c = [i - 0.4 for i in literature_pic_weight]
lineAcc_2 = axDRR.bar(c, [results[0][1], results[1][1], results[2][1], results[3][1], results[4][1], results[5][1],
                          results[6][1]], color=color_list[1], width=0.8,
                      )
d = [i + 0.4 for i in literature_pic_weight]
lineAcc_3 = axBF.bar(d, [int(results[0][2]), int(results[1][2]), int(results[2][2]), int(results[3][2]),
                         int(results[4][2]), int(results[5][2]), int(results[6][2])], color=color_list[2], width=0.8,
                     )
e = [i + 1.2 for i in literature_pic_weight]
lineAcc_4 = axDRR.bar(e, [results[0][3], results[1][3], results[2][3], results[3][3], results[4][3], results[5][3],
                          results[6][3]], color=color_list[3], width=0.8, )
yminorLocator = MultipleLocator(1)
axBF.yaxis.set_minor_locator(yminorLocator)
axDRR.set_xticks([])
axBF.set_xticks(literature_pic_weight)
axBF.set_xticklabels(fun_name)
axBF.set_ylim([0, 40])
axDRR.set_ylim([0, 0.8])
labels = axBF.get_yticklabels() + axDRR.get_yticklabels()
[label.set_fontname('Times New Roman') for label in labels]
labels = axBF.get_xticklabels() + axBF.get_yticklabels() + axDRR.get_yticklabels()
[label.set_fontsize(12) for label in labels]
labels = axBF.get_xticklabels()
for label in labels[1:]:
    label.set_fontname('Times New Roman')
    if label == labels[-1]:
        label.set_fontweight('bold')

axBF.set_xlabel('不同特征选择算法', {'size': 12})
axBF.set_ylabel('$\mathrm{\itN^{\Phi_{\mathrm{best}}}}$', {'size': 12})
axDRR.set_ylabel('$\mathrm{\itDRR}$', {'size': 12})
axBF.legend((lineAcc_1, lineAcc_2, lineAcc_3, lineAcc_4), method_name, fontsize=12, framealpha=0.2,
            bbox_to_anchor=(0, 0.95, 1, 0.2),
            loc='upper center', ncol=4, columnspacing=0.5,
            handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False)
results_T = np.array(results).T
num = 0
for a, b in zip(literature_pic_weight, list(results_T[0])):
    if num == len(list(results_T[0])) - 1:
        axBF.text(a-1.2, b-2, str('%d' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman', fontweight='bold')
    else:
        axBF.text(a-1.2, b-2, str('%d' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman')
    num += 1
num = 0
for a, b in zip(literature_pic_weight, list(results_T[1])):
    if num == 0:
        axDRR.text(a - 0.4, b+0.03 , str('%d' % b), ha='center', va='center', fontsize=12,
                   fontproperties='Times New Roman')
    elif num == len(list(results_T[0])) - 1:
        axDRR.text(a-0.4, b-0.09, str('%.4f' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman', fontweight='bold',rotation=90)
    elif num==4:
        axDRR.text(a - 0.4, b + 0.09, str('%.4f' % b), ha='center', va='center', fontsize=12,
                   fontproperties='Times New Roman', rotation=90)
    else:
        axDRR.text(a-0.4, b-0.09, str('%.4f' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman',rotation=90)
    num += 1
num = 0
for a, b in zip(literature_pic_weight, list(results_T[2])):
    if num == len(list(results_T[0])) - 1:
        axBF.text(a+0.4, b-2, str('%d' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman', fontweight='bold')
    else:
        axBF.text(a+0.4, b-2, str('%d' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman')
    num += 1
num = 0
for a, b in zip(literature_pic_weight, list(results_T[3])):
    if num == 0:
        axDRR.text(a+1.2, b+0.03 , str('%d' % b), ha='center', va='center', fontsize=12,
                   fontproperties='Times New Roman')
    elif num == len(list(results_T[0])) - 1:
        axDRR.text(a+1.2, b-0.09, str('%.4f' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman', fontweight='bold',rotation=90)
    elif num==4:
        axDRR.text(a+1.2, b + 0.09, str('%.4f' % b), ha='center', va='center', fontsize=12,
                   fontproperties='Times New Roman', rotation=90)
    else:
        axDRR.text(a+1.2, b-0.09, str('%.4f' % b), ha='center', va='center', fontsize=12,
                  fontproperties='Times New Roman',rotation=90)
    num += 1
plt.savefig('多组柱状图.svg', bbox_inches='tight', pad_inches=0)
# plt.savefig('多组柱状图.png', bbox_inches='tight', pad_inches=0,dpi=1200)
plt.show()

在这里插入图片描述

(10)双向柱状图

# 代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
# 部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
# 感谢在我科研绘图过程中提供帮助的各位博主!

# 导包
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import rcParams

# 设置配置文件
config = {
    # 衬线字体(衬线字体, 宋体和Times New Roman属于这类字体)
    "font.family": 'serif',
    # matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
    "mathtext.fontset": 'stix',
    # 设置绘图时全局字体为宋体(SimSun)
    "font.serif": ['SimSun'],
}
# 修改运行时配置参数的方法(Matplotlib使用matplotlibrc配置文件来自定义图形的各种属性,称之为rc配置或rc参数(rcParams))
rcParams.update(config)
# 设置图例、坐标轴标题、x和y轴值
paper_list = ['本文', '[$\mathrm{41}$]', '[$\mathrm{38}$]', '[$\mathrm{33}$]', '[$\mathrm{28}$]', '[$\mathrm{27}$]',
              '[$\mathrm{26}$]', '[$\mathrm{25}$]', '[$\mathrm{22}$]']
label_list = ['$\mathrm{\itFPR}$', '$\mathrm{\itFNR}$']
x = np.array([0.0017,0.0258,0.0192,0.0061,0.0029,0.0405,0.0322,0.0509,0.0504])  # FPR
y = np.array([0.0129,0.0517,0.0681,0.0328,0.1000,0.2067,0.0500,0.1131,0.1238])  # FNR

fig, ax1 = plt.subplots()
# 绘制柱状图
# 向左方面的柱状图,对应的数据取负
ax1.barh(range(len(x)), -x, color='#FFD39A')
# 向左方面的柱状图,对应的数据取正
ax1.barh(range(len(y)), y, color='#9ED2C6')
# 数值数据轴刻度数
ax1.set_yticks(range(len(paper_list)))
# 设置数据轴显示的数值和字号
ax1.set_yticklabels(paper_list, size=12)
ax1.set_xticks([-0.05, 0.00, 0.05, 0.1, 0.15, 0.20])
ax1.set_xticklabels([0.05, 0.00, 0.05, 0.1, 0.15, 0.20], size=12)
labels = ax1.get_xticklabels()
[label.set_fontname('Times New Roman') for label in labels]
# 设置“文献”轴,除“本文外”其余字体为新罗马
labels = ax1.get_yticklabels()
for i in range(len(labels)):
    if i != 0:
        labels[i].set_fontname('Times New Roman')
labels = ax1.get_xticklabels() + ax1.get_yticklabels()
[label.set_fontsize(12) for label in labels]
labels = ax1.get_yticklabels()
ax1.set_xlabel('数值', size=12)
ax1.set_ylabel('文献', size=12)
num = 0
for a, b in zip(x, range(len(paper_list))):
    if num == 0:
        ax1.text(-a - 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman', fontweight='bold')
    elif num == 1 or num == 2 or num == 4:
        ax1.text(-a - 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    elif num == 3:
        ax1.text(-a - 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    else:
        ax1.text(-a + 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    num += 1
num = 0
for a, b in zip(y, range(len(paper_list))):
    if num == 0:
        ax1.text(a + 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman', fontweight='bold')
    elif num == 5:
        ax1.text(a - 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    else:
        ax1.text(a + 0.015, b, str('%.4f' % a), ha='center', va='center', fontsize=12,
                 fontproperties='Times New Roman')
    num += 1
plt.legend(label_list, fontsize=12, framealpha=0.2, ncol=1, loc='upper right',
           columnspacing=0.5,
           handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False)
# 绘制x=0的竖线
plt.axvline(0, alpha=0.5, linewidth=1, color='#15eaff')
plt.savefig('双向柱状图.svg', bbox_inches='tight', pad_inches=0)
plt.show()

在这里插入图片描述

(11)三维柱状图

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
import numpy as np
from matplotlib import rcParams
from matplotlib.pyplot import MultipleLocator

config = {  # SimSun
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
}
rcParams.update(config)
# 创建画布
fig = plt.figure()
# 创建3D坐标系
# axes3d = Axes3D(fig, auto_add_to_figure=False)
axes3d = Axes3D(fig)
fig.clear()
fig.add_axes(axes3d)
zs = range(4)
left = np.arange(0, 12)
num = (np.array([
    [0.8907, 0.8922, 0.7820, 0.8910],
    [0.8943, 0.8947, 0.7888, 0.8943],
    [0.9410, 0.9484, 0.8794, 0.9394],
    [0.8538, 0.8666, 0.7228, 0.8652],
    [0.9900, 0.9171, 0.9123, 0.9467],
    [0.9513, 0, 0, 0],
    [0.9800, 0, 0, 0],
    [0.9836, 0.9599, 0.9714, 0.9787],
    [0.9300, 0, 0, 0],
    [0.9507, 0.9486, 0.9018, 0.9500],
    [0.9482, 0.9359, 0.8927, 0.9481],
    [0.9924, 0.9924, 0.9849, 0.9963],

])).T
num = np.where(num == 0, num, num - 0.7)
final_line = []
for i in range(len(zs)):
    z = zs[i]
    line = axes3d.bar(left, num[i], zs=z, zdir='x',
                      color=['#8BBCCC', '#483838', '#FFD8A9', 'red', 'green', 'purple', 'yellow', '#99cc00', '#00a8e1', 'gray',
                             'orange', '#0000ff'],
                      alpha=0.8)
    final_line.append(line)
# axes3d.set_zlim(0.7,1)
axes3d.set_xticks(zs)
axes3d.set_xticklabels(
    ['$\mathrm{\itAcc}$', '$\mathrm{\itF}$-$\mathrm{\itscore}$',
     '$\mathrm{\itMCC}$', '$\mathrm{\itGM}$'])
axes3d.set_yticks(left)
axes3d.set_yticklabels([])
# axes3d.set_yticklabels(['[$\mathrm{9}$]', '[$\mathrm{10}$]', '[$\mathrm{11}$]', '[$\mathrm{12}$]', '[$\mathrm{14}$]',
#                         '[$\mathrm{16}$]', '[$\mathrm{19}$]', '[$\mathrm{23}$]', '本文'])
file_name = ['[$\mathrm{22}$]', '[$\mathrm{25}$]', '[$\mathrm{26}$]', '[$\mathrm{27}$]', '[$\mathrm{28}$]',
             '[$\mathrm{29}$]', '[$\mathrm{31}$]', '[$\mathrm{33}$]', '[$\mathrm{37}$]', '[$\mathrm{38}$]',
             '[$\mathrm{41}$]', '本文']
for d in np.arange(0, 12):
    # ax.text(d, 10.75, 0, "%d" % d, color=color, size=size, ha="center", va="center")
    if d != 11:
        axes3d.text(3.5, d, 0, "%s" % file_name[d], ha="center", va="center", color='black', size=10)
    else:
        axes3d.text(3.5, d, 0, "%s" % '本文', ha="center", va="center", color='black', size=10)
labels = axes3d.get_xticklabels() + axes3d.get_zticklabels()
[label.set_fontname('Times New Roman') for label in labels]
labels = axes3d.get_xticklabels() + axes3d.get_zticklabels()
[label.set_fontsize(12) for label in labels]
axes3d.set_zticks([0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3])
axes3d.set_zticklabels(['0.70', '0.75', '0.80', '0.85', '0.90', '0.95', '1.00'])
axes3d.set_xlabel('评估指标', {'size': 12})
axes3d.set_ylabel('文献', {'size': 12})
axes3d.set_zlabel('数值', {'size': 12})
labelss = axes3d.legend(final_line[0],
                        ['CNN-LSTM$^{[22]}$', 'FSL-ANN$^{[25]}}$', 'GCN$^{[26]}}$', 'MNSWOA-IPM-RF$^{[27]}}$',
                         'NCI-LR$^{[28]}}$', 'RBM$^{[29]}}$', 'BotCatcher$^{[31]}}$',
                         'DenseNet-BiLSTM$^{[33]}}$', 'RiskID$^{[37]}}$', 'OFA-SVM$^{[38]}}$', 'TRUSTED-HAC$^{[41]}}$',
                         r'$\mathrm{\bfTSHHM}$$\mathrm{(}$本文$\mathrm{)}$'],
                        fontsize=12, framealpha=0.2,
                        bbox_to_anchor=(0.8, 0.6, 1, 0.2),
                        loc='upper center', ncol=1, columnspacing=0.5,
                        handletextpad=0.1, handlelength=1.8, labelspacing=0.2, frameon=False).get_texts()
for i in range(len(labelss)):
    if i != len(labelss) - 1:
        labelss[i].set_fontname('Times New Roman')
plt.savefig('三维柱状图.svg', bbox_inches='tight', pad_inches=0)
# plt.savefig('三维柱状图.png', bbox_inches='tight', pad_inches=0,dpi=1200)
plt.show()

在这里插入图片描述

(12)构建平面直角坐标系

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.pyplot import MultipleLocator

config = {  # SimSun
    "font.family": 'serif',
    "mathtext.fontset": 'stix',
    "font.serif": ['SimSun'],
    "axes.unicode_minus": False,
}
rcParams.update(config)

# 设置画布
fig, ax1 = plt.subplots(figsize=(24, 24))

# 去掉右边框和上边框颜色
ax1.spines['right'].set_color('none')
ax1.spines['top'].set_color('none')

ax1.set_xticks(range(-12, 13))
ax1.set_yticks(range(-1, 24))

# 设置坐标轴范围
ax1.set_xlim(-12, 12)
ax1.set_ylim(-1, 23)

# 移动左边框和下边框到中间(set_position的参数是元组)
ax1.spines['left'].set_position(('data', 0))
ax1.spines['bottom'].set_position(('data', 0))

# 在坐标系中绘制圆
# 圆心坐标,半径,内部及边缘填充颜色
draw_circle = plt.Circle((0, 11), 11, fc='w', ec='b')
ax1.set_aspect(1)
ax1.add_artist(draw_circle)
ax1.plot(0, 11, c='b', marker='o')
# 画坐标轴箭头
ax1.arrow(0, 0, 11.5, 0, head_width=0.5, head_length=0.5, color='k')
ax1.arrow(0, 0, 0, 22.5, head_width=0.5, head_length=0.5, color='k')
t = 2 ** 0.5
square1_point = [[-10, 11], [-2 * t, 11 + 2 * t], [0, 19], [4 * t, 11 + 4 * t], [9, 11], [4.5 * t, 11 - 4.5 * t], [0, 7]
    , [-4 * t, 11 - 4 * t]]
square1_point_str = ["$\mathrm{P_1(\itx_1,\ity_1)=(-10,11)}$",
                     "$\mathrm{P_2(\itx_2,\ity_2)=(-2\sqrt{2},11+2\sqrt{2})}$",
                     "$\mathrm{P_3(\itx_3,\ity_3)=(0,19)}$", "$\mathrm{P_4(\itx_4,\ity_4)=(4\sqrt{2},11+4\sqrt{2})}$",
                     "$\mathrm{P_5(\itx_5,\ity_5)=(9,11)}$",
                     "$\mathrm{P_6(\itx_6,\ity_6)=(\\frac{9}{2}\sqrt{2},11-\\frac{9}{2}\sqrt{2})}$",
                     "$\mathrm{P_7(\itx_7,\ity_7)=(0,7)}$", "$\mathrm{P_8(\itx_8,\ity_8)=(-4\sqrt{2},11-4\sqrt{2})}$"]
square1_point_str2 = ["$\mathrm{P_1^{'}}$", "$\mathrm{P_2^{'}}$", "$\mathrm{P_3^{'}}}$","$\mathrm{P_4^{'}}$",
                      "$\mathrm{P_5^{'}}$", "$\mathrm{P_6^{'}}$", "$\mathrm{P_7^{'}}$", "$\mathrm{P_8^{'}}$"]
square1 = plt.Polygon(xy=square1_point, fc='#ff8080', ec='black', linewidth=3, alpha=0.8)
ax1.add_artist(square1)
for i in range(len(square1_point)):
    ax1.plot(square1_point[i][0], square1_point[i][1], c='black', marker='H', markersize=18)
    ax1.plot(square1_point[i][0], 0, c='black', marker='o', markersize=18)
    ax1.vlines(square1_point[i][0], ymin=0, ymax=square1_point[i][1], color='black', linewidth=2, linestyles='--')
    ax1.annotate(square1_point_str[i],
                 xy=(square1_point[i][0], square1_point[i][1] + 0.5),
                 xycoords='data',
                 xytext=(square1_point[i][0], square1_point[i][1] + 0.5), ha='center', size=28)
    if i ==2 :
        ax1.annotate(square1_point_str2[i],
                     xy=(square1_point[i][0], 1.5),
                     xycoords='data',
                     xytext=(square1_point[i][0], 1.5), ha='center', size=28)
    else:
        ax1.annotate(square1_point_str2[i],
                     xy=(square1_point[i][0], 0.5),
                     xycoords='data',
                     xytext=(square1_point[i][0], 0.5), ha='center', size=28)
ax1.annotate("$\mathrm{\it{PA}}$",
                     xy=(2,12),
                     xycoords='data',
                     xytext=(2,12), ha='center', size=36)
ax1.annotate("$\mathrm{\itx}$轴$\mathrm{(\itf_7}$方向$\mathrm{)}$",
                     xy=(11,0.5),
                     xycoords='data',
                     xytext=(11,0.5), ha='center', size=36)
ax1.annotate("$\mathrm{\ity}$轴$\mathrm{(\itf_1}$方向$\mathrm{)}$",
                     xy=(2,22.5),
                     xycoords='data',
                     xytext=(2,22.5), ha='center', size=36)
ax1.annotate("$\mathrm{\itf_5=(0,0)}$",
                     xy=(0,-1),
                     xycoords='data',
                     xytext=(0,-1), ha='center', size=36)
ax1.annotate("同心圆最外侧圆,\n同心圆圆心$\mathrm{(0,11)}$", xy=(-8, 18.5), xycoords='data', ha='center',
                 bbox=dict(boxstyle="round", fc="none", ec="gray"), size=28,
                 xytext=(-8, 21),
                 arrowprops=dict(arrowstyle="->"))
ax1.annotate("待求解多边形端点", xy=(4 * t, 11 + 4 * t), xycoords='data', ha='right',
                 bbox=dict(boxstyle="round", fc="none", ec="gray"), size=28,
                 xytext=(5, 15),
                 arrowprops=dict(arrowstyle="->"))
ax1.annotate("投影点", xy=(0, 0), xycoords='data', ha='right',
                 bbox=dict(boxstyle="round", fc="none", ec="gray"), size=28,
                 xytext=(2, 1),
                 arrowprops=dict(arrowstyle="->"))
# 添加网格
plt.grid(True, linestyle='--', alpha=0.5)

labels = ax1.get_yticklabels() + ax1.get_xticklabels()
[label.set_fontname('Times New Roman') for label in labels]
y_labels = ax1.get_yticklabels() + ax1.get_xticklabels()
[label.set_fontsize(28) for label in y_labels]

plt.savefig('构建平面直角坐标系.svg', bbox_inches='tight', pad_inches=0)
# plt.savefig('构建平面直角坐标系.png', bbox_inches='tight', pad_inches=0,dpi=1200)
# 图像显示
plt.show()

在这里插入图片描述

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持就是胜利^-^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值