📣嘿,兄弟们!
用过Matplotlib的都知道,那默认图表丑得能让人当场裂开😱!
别慌,今天老哥我手把手教你们把折线图加上骚气满满的渐变填充。
保证让咱的图表从“土狗”进化成“赛博土狗”!💎🐶
废话不多说,直接先看效果!👇
有需要的朋友关注公众号【小Z的科研日常】,获取更多内容。
01、开场先导库,准备起飞!
干活前得把家伙事儿备齐。以下是咱们要用到的库,直接抄走,别客气!
import pandas as pd
import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib import rcParams
from matplotlib.path import Path
from matplotlib.patches import PathPatch
np.random.seed(38)
为了给你们演示,老哥我先用代码随机搓一波数据。你们有自己的数据就直接替换。
dates = pd.date_range(start='2024-02-01', periods=100, freq='D')
initial_rate = 75
drift = 0.003
volatility = 0.1
returns = np.random.normal(drift, volatility, len(dates))
rates = initial_rate * np.cumprod(1 + returns)
x, y = dates, rates
02、默认图表丑的一批,快来围观!
咱们先用Matplotlib默认设置画个图,看看有多辣眼睛👻。
fix, ax = plt.subplots(figsize=(8, 4))
ax.plot(dates, rates)
ax.xaxis.set_major_locator(mdates.DayLocator(interval=30))
plt.show()
兄弟们,这图丑得我都不好意思拿出手!线条像毛毛虫,刻度乱七八糟,简直是视觉污染啊!
02、初步美化四步走
咱们先给图表加个标题,调调字体,再把线条颜色和粗细改改,让它看起来至少像个人样。
# 创建图形和坐标轴
fig, ax = plt.subplots(figsize=(10, 6))
# 加个骚气标题
plt.title("Title", fontsize=18, color="black")
# 设置字体,高端大气
rcParams['font.family'] = 'DejaVu Sans'
rcParams['font.size'] = 14
# Y轴刻度放左边
ax.yaxis.tick_left()
ax.yaxis.set_label_position("left")
# 主线换个帅气颜色
ax.plot(dates, rates, color='#268358', linewidth=2)
# 刻度颜色调黑
ax.tick_params(axis="x", colors="black")
ax.tick_params(axis="y", colors="black")
ax.spines["bottom"].set_color("black")
plt.show()
怎么样?这样看起来是不是清爽一些?
咱们继续给背景加个简约网格,再把X轴第一个刻度整出年份,刻度颜色调浅点,显得低调又高级。
# 加个虚线网格
ax.grid(color="gray", linestyle=(0, (10, 10)), linewidth=0.5, alpha=0.6)
# X轴刻度黑色,Y轴隐藏
ax.tick_params(axis="x", colors="black")
ax.tick_params(axis="y", left=False, labelleft=False)
# 去掉多余边框
ax.spines["top"].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines["bottom"].set_color("black")
ax.spines['left'].set_color('white')
ax.spines['left'].set_linewidth(1)
# 自定义X轴日期格式,首刻度带年份
def custom_date_formatter(t, pos, dates, x_interval):
date = dates[pos * x_interval]
if pos == 0:
return date.strftime('%d %b \'%y') # 首刻度带年份
else:
return date.strftime('%d %b') # 其他只显示日月
ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: custom_date_formatter(x, pos, dates=dates, x_interval=30)))
# 刻度标签调浅灰色
[t.set_color('#808079') for t in ax.yaxis.get_ticklabels()]
[t.set_color('#808079') for t in ax.xaxis.get_ticklabels()]
兄弟们,看到没?这图现在是不是有点内味儿了?但老哥我还觉得差点灵魂——对,就是那炫酷的渐变填充!
04、骚操作:给曲线下加渐变填充
Matplotlib默认没这功能,但咱能搞!思路是造个渐变图像,再用曲线剪裁它。听起来高大上?别怕,老哥带你们一步步飞。
# X轴转成数值
numeric_x = np.array([i for i in range(len(x))])
# 补齐路径点,形成封闭区域
numeric_x_patch = np.append(numeric_x, max(numeric_x))
numeric_x_patch = np.append(numeric_x_patch[0], numeric_x_patch)
y_patch = np.append(y, 0)
y_patch = np.append(0, y_patch)
# 创建路径并裁剪
path = Path(np.array([numeric_x_patch, y_patch]).transpose())
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)
# 加渐变填充
ax.imshow(numeric_x.reshape(len(numeric_x), 1), interpolation="bicubic",
cmap=plt.cm.Greens, # 绿色渐变
origin='lower',
alpha=0.3, # 透明度
extent=[min(numeric_x), max(numeric_x), min(y_patch), max(y_patch) * 1.2],
aspect="auto", clip_path=patch, clip_on=True)
兄弟们,这渐变一加,图直接从村口理发店飞升到米兰时装周!
我更喜欢 Google Slides添加一些细节、标题、圆角边框和一些数字指示器,下面是效果展示。
05、完整代码:一键抄走不谢!
import pandas as pd
import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib import rcParams
from matplotlib.path import Path
from matplotlib.patches import PathPatch
# 设置随机种子,确保每次运行结果一致
np.random.seed(38)
# 数据生成部分
dates = pd.date_range(start='2024-02-01', periods=100, freq='D') # 生成从2024年2月1日起的100天日期序列
initial_rate = 75 # 设置初始值75
drift = 0.003 # 设置漂移率,每天平均增长率
volatility = 0.1 # 设置波动率,控制数据的随机起伏
returns = np.random.normal(drift, volatility, len(dates)) # 生成正态分布的随机收益率
rates = initial_rate * np.cumprod(1 + returns) # 根据初始值和累计收益率计算每天的数据
x, y = dates, rates # X轴为日期,Y轴为数据
# 图表通用参数设置
fig, ax = plt.subplots(figsize=(10, 6)) # 创建一个10x6英寸的画布
plt.title("Daily visitors", fontsize=18, color="black") # 设置标题“Daily visitors”,字体大小18,黑色
rcParams['font.family'] = 'DejaVu Sans' # 设置全局字体为DejaVu Sans
rcParams['font.size'] = 14 # 设置全局字体大小为14
# 将Y轴移到右侧
ax.yaxis.tick_right() # Y轴刻度显示在右边
ax.yaxis.set_label_position("right") # Y轴标签位置设为右边
# 设置X轴和Y轴
x_interval = 21 # X轴刻度间隔设为21天
ax.xaxis.set_major_formatter(mdates.DateFormatter("%d %b")) # X轴日期格式设为“日 月”(如“01 Feb”)
ax.xaxis.set_major_locator(mdates.DayLocator(interval=x_interval)) # X轴每21天显示一个刻度
ax.yaxis.set_major_locator(ticker.MultipleLocator(50)) # Y轴每50个单位显示一个刻度
# 添加网格
ax.grid(color="gray", linestyle=(0, (10, 10)), linewidth=0.5, alpha=0.6) # 添加灰色虚线网格,透明度0.6
ax.tick_params(axis="x", colors="black") # X轴刻度颜色设为黑色
ax.tick_params(axis="y", left=False, labelleft=False) # 隐藏Y轴左侧刻度和标签
# 设置边框样式
ax.spines["top"].set_visible(False) # 隐藏顶部边框
ax.spines['right'].set_visible(False) # 隐藏右侧边框
ax.spines["bottom"].set_color("black") # 底部边框设为黑色
ax.spines['left'].set_color('white') # 左侧边框设为白色
ax.spines['left'].set_linewidth(1) # 左侧边框线宽设为1
# 移除Y轴刻度线
ax.tick_params(axis='y', length=0) # Y轴刻度线长度设为0,即不显示
# 自定义X轴日期格式,第一个刻度带年份
def custom_date_formatter(t, pos, dates, x_interval):
date = dates[pos * x_interval] # 根据位置获取对应的日期
if pos == 0:
return date.strftime('%d %b \'%y') # 第一个刻度显示“日 月 '年”(如“01 Feb '24”)
else:
return date.strftime('%d %b') # 其他刻度显示“日 月”(如“22 Feb”)
ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: custom_date_formatter(x, pos, dates=dates, x_interval=x_interval)))
# 设置刻度标签颜色
[t.set_color('#808079') for t in ax.yaxis.get_ticklabels()] # Y轴刻度标签颜色设为浅灰色
[t.set_color('#808079') for t in ax.xaxis.get_ticklabels()] # X轴刻度标签颜色设为浅灰色
# 创建渐变填充
numeric_x = np.array([i for i in range(len(x))]) # 将X轴日期转为数值序列(0到99)
numeric_x_patch = np.append(numeric_x, max(numeric_x)) # 在末尾添加最大值
numeric_x_patch = np.append(numeric_x_patch[0], numeric_x_patch) # 在开头添加0,形成闭合路径
y_patch = np.append(y, 0) # 在Y值末尾添加0
y_patch = np.append(0, y_patch) # 在Y值开头添加0,形成闭合区域
path = Path(np.array([numeric_x_patch, y_patch]).transpose()) # 创建一个由X和Y坐标组成的路径
patch = PathPatch(path, facecolor='none') # 创建路径补丁,填充颜色为空
plt.gca().add_patch(patch) # 将补丁添加到当前图表
# 添加渐变效果
ax.imshow(numeric_x.reshape(len(numeric_x), 1), interpolation="bicubic", # 使用imshow绘制渐变,bicubic插值使过渡平滑
cmap=plt.cm.Greens, # 使用绿色渐变色
origin='lower', # 从底部开始渐变
alpha=0.3, # 透明度设为0.3
extent=[min(numeric_x), max(numeric_x), min(y_patch), max(y_patch) * 1.2], # 设置渐变区域范围,Y轴上限放大1.2倍
aspect="auto", clip_path=patch, clip_on=True) # 自动调整宽高比,裁剪到路径区域内
# 绘制主线
y_chart = y_patch # 使用补丁的Y值绘制主线
y_chart[0] = y_chart[1] # 将起始点设为第二个点值,避免突变
y_chart[-1] = y_chart[-2] # 将末尾点设为倒数第二个点值,避免突变
ax.plot(numeric_x_patch, y_chart, color='#268358', linewidth=2) # 绘制深绿色主线,线宽2
# 修复imshow可能出现的灰线问题
ax.plot([max(numeric_x_patch), max(numeric_x_patch)], [0, max(y)], color='white', linewidth=2) # 在右侧画一条白线覆盖灰线
# 保存高质量图片并显示
plt.savefig('high_quality_plot.png', dpi=300, bbox_inches='tight') # 保存为300dpi的高清图片,紧凑布局
plt.show() # 显示图表
兄弟们,学会了没?这Matplotlib折线图美化大法是不是简单又实用?
从此告别丑图,你的图表也能C位出道!
赶紧点赞+收藏+转发,让更多兄弟一起变强!
下次老哥我再掏点数据可视化的硬核干货,敬请期待啊!🚀