python - 从 python 创建 "The Economist"样式图

标签 python matplotlib seaborn

使用 python 和 marplotlib 以及像 seaborn 这样的工具,我想创建一个像经济学人这样的图表(因为我认为这种风格很棒。)

Greece Debt

这是一个时间序列图,我想重现的关键是带有标签的水平网格线与带有刻度线的较低水平轴相匹配。网格线两端的不同颜色标签将是一个奖励,具有相应的标题(左对齐和右对齐)。注释将是双重奖励。

我尝试使用 seaborn 制作类似的东西,但无法迈出第一步。

最佳答案

不完美(我没玩多久),但为了让您了解您需要使用哪种 Matplotlib 方法来按照您想要的方式自定义绘图,下面有一些代码。

请注意,要像这样微调绘图,很难将内容和表示分开(您可能必须手动设置刻度标签等,因此如果您更改数据,它不会自动工作)。 The Economist 的绘图人员显然这样做是因为他们似乎将左上角的刻度标签弄错了(280 应该是 260)。

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as ticker
from datetime import datetime

# Load in some sample data
bond_yields = np.loadtxt('bond_yields.txt',
                         converters={0: mdates.strpdate2num('%Y-%m-%d')},
                         dtype = {'names': ('date', 'bond_yield'),
                                  'formats': (datetime, float)})
bank_deposits = np.loadtxt('bank_deposits.txt',
                         converters={0: mdates.strpdate2num('%Y-%m-%d')},
                         dtype = {'names': ('date', 'bank_deposits'),
                                  'formats': (datetime, float)})

# Bond yields line is in light blue, bank deposits line in dark red:
bond_yield_color = (0.424, 0.153, 0.090)
bank_deposits_color = (0.255, 0.627, 0.843)

# Set up a figure, and twin the x-axis so we can have two different y-axes
fig = plt.figure(figsize=(8, 4), frameon=False, facecolor='white')
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
# Make sure the gridlines don't end up on top of the plotted data
ax1.set_axisbelow(True)
ax2.set_axisbelow(True)

# The light gray, horizontal gridlines
ax1.yaxis.grid(True, color='0.65', ls='-', lw=1.5, zorder=0)

# Plot the data
l1, = ax1.plot(bank_deposits['date'], bank_deposits['bank_deposits'],
         c=bank_deposits_color, lw=3.5)
l2, = ax2.plot(bond_yields['date'], bond_yields['bond_yield'],
         c=bond_yield_color, lw=3.5)

# Set the y-tick ranges: chosen so that ax2 labels will match the ax1 gridlines
ax1.set_yticks(range(120,280,20))
ax2.set_yticks(range(0, 40, 5))

# Turn off spines left, top, bottom and right (do it twice because of the twinning)
ax1.spines['left'].set_visible(False)
ax1.spines['right'].set_visible(False)
ax1.spines['top'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax2.spines['right'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax1.spines['bottom'].set_visible(False)
ax2.spines['bottom'].set_visible(False)
# We do want ticks on the bottom x-axis only
ax1.xaxis.set_ticks_position('bottom')
ax2.xaxis.set_ticks_position('bottom')

# Remove ticks from the y-axes
ax1.tick_params(axis='y', length=0)
ax2.tick_params(axis='y', length=0)

# Set tick-labels for the two y-axes in the appropriate colors
for tick_label in ax1.yaxis.get_ticklabels():
    tick_label.set_fontsize(12)
    tick_label.set_color(bank_deposits_color)
for tick_label in ax2.yaxis.get_ticklabels():
    tick_label.set_fontsize(12)
    tick_label.set_color(bond_yield_color)

# Set the x-axis tick marks to two-digit years
ax1.xaxis.set_major_locator(mdates.YearLocator())
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%y'))

# Tweak the x-axis tick label sizes
for tick in ax1.xaxis.get_major_ticks():
    tick.label.set_fontsize(12)
    tick.label.set_horizontalalignment('center')

# Lengthen the bottom x-ticks and set them to dark gray
ax1.tick_params(direction='in', axis='x', length=7, color='0.1')

# Add the line legends as annotations
ax1.annotate(u'private-sector bank deposits, €bn', xy=(0.09, 0.95),
             xycoords='figure fraction', size=12, color=bank_deposits_color,
             fontstyle='italic')
ax2.annotate(u'ten-year government bond yield, %', xy=(0.6, 0.95),
             xycoords='figure fraction', size=12, color=bond_yield_color,
             fontstyle='italic')

# Add an annotation at the date of the first bail-out. relpos=(0,0) ensures
# that the label lines up on the right of a vertical line
first_bailout_date = datetime.strptime('2010-05-02', '%Y-%m-%d')
xpos = mdates.date2num(first_bailout_date)
ax1.annotate(u'FIRST BAIL-OUT', xy=(xpos, 120), xytext=(xpos, 250), color='r',
             arrowprops=dict(arrowstyle='-', edgecolor='r', ls='dashed',
             relpos=(0,0)), fontsize=9, fontstyle='italic')

fig.savefig('fig.png', facecolor=fig.get_facecolor(), edgecolor='none')

enter image description here

关于python - 从 python 创建 "The Economist"样式图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29859565/

相关文章:

python - 线图不显示轴中的所有日期

python - 迭代 python 数组并找到 50 个值的平均值/最小值/最大值

python - 如何压缩字符串?

python - 通过直方图测量图像的颜色

python - 如何在 Seaborn 中覆盖 ax 具有不同列的屏蔽图? - Python

matplotlib - 基于色调/调色板的条形图中的边缘颜色

python - Gunicorn worker 无论如何都会超时

python - 带有嵌套选择的 SQL Delete 语句

matplotlib - 根据matplotlib中y值更改曲线的颜色

python - 从 matplotlib : boxplot 中查找离群点