I am trying to reproduce this: enter image description here

使用以下代码:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.lines import Line2D

colors = ["#CC5A43","#5375D4"]*3

data = {
    "year": [2004, 2022, 2004, 2022, 2004, 2022],
    "countries" : ["Sweden", "Sweden", "Denmark", "Denmark", "Norway", "Norway"],
    "sites": [13,15,4,10,5,8]
}
df= pd.DataFrame(data)

df['pct_change'] = df.groupby('countries', sort=True)['sites'].apply(
     lambda x: x.pct_change()).to_numpy()*-1
df['ctry_code'] = df.countries.astype(str).str[:2].astype(str).str.upper()
df = df.sort_values(['countries','year'], ascending=True ).reset_index(drop=True)
df['diff'] = df.groupby(['countries'])['sites'].diff()
df['diff'].fillna(df.sites, inplace=True)
countries = df.countries.unique()
code = df.ctry_code.unique()
pct_change = df.pct_change

x_coord = df.groupby('countries')['diff'].apply(lambda x: x.values) #convert the columns into numpy 2D array

fig, ax = plt.subplots(figsize=(6,5), facecolor = "#FFFFFF")
import matplotlib.cm
# use a colormap
cmap = plt.cm.RdBu

for i, (color, x_c, country) in enumerate(zip(colors,x_coord, countries)):
    ax.broken_barh([x_c], (i-0.2,0.4),facecolors=cmap(0.7),alpha= 0.2)

ax.scatter( df.sites, df.countries, marker="D", s=300, color = colors)

ax.set(xlim=[0, 16], ylim=[-1, 3])

ax.xaxis.set_ticks(np.arange(0,20,5),labels = [0,5,10,15])
ax.tick_params(axis="x", which="major",length=0,labelsize=14,colors= '#C8C9C9')

# Major ticks every 20, minor ticks every 5
major_ticks = np.arange(0, 16, 1)
ax.set_xticks(major_ticks)
ax.grid(which='major', axis='x', linestyle='-', alpha=0.4, color = "#C8C9C9")
ax.set_axisbelow(True)
plt.yticks([])
plt.box(False)

#add legend
labels = ['2004','2022']
colors = ["#5375D4","#CC5A43",]
lines = [Line2D([0], [0], color=c,  marker='D',linestyle='', markersize=12,) for c in colors]
leg = ax.get_legend()
plt.figlegend( lines,labels,
           labelcolor="#C8C9C9",
           bbox_to_anchor=(0.3, -0.1), loc="lower center",
            ncols = 2,frameon=False, fontsize= 12)

这就产生了这样的结果:

enter image description here

我的问题是,我该如何对破碎的Barh图进行渐变呢?我试着在脸部 colored颜色 上做了一个cmap,但没有成功.

我也try 过使用ax.barh和ax.lot,但仍然卡住了:(

推荐答案

参考答案How to fill matplotlib bars with a gradient?

我对函数gradientbars做了一些修改,在其中添加了一些注释.

此外,我还更改了scatter图的大小,以使其与broken_barh和消失的legend保持一致.

以下是完整的代码:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.lines import Line2D
from matplotlib.colors import LinearSegmentedColormap

def gradientbars(bars, ax):
    colors = [(1, 0, 0), (0, 0, 1), ] # first color is red, last is blue
    cm = LinearSegmentedColormap.from_list(
            "Custom", colors, N=256) # Conver to color map 
    mat = np.indices((10,10))[1] # define a matrix for imshow
    lim = ax.get_xlim()+ax.get_ylim()
    for bar in bars:
        bar.set_zorder(1)
        bar.set_facecolor("none")
        
        # get the coordinates of the rectangle
        x_all = bar.get_paths()[0].vertices[:, 0]
        y_all = bar.get_paths()[0].vertices[:, 1]
        
        # Get the first coordinate (lower left corner)
        x,y = x_all[0], y_all[0]
        # Get the height and width of the rectangle
        h, w = max(y_all) - min(y_all), max(x_all) - min(x_all)
        # Show the colormap 
        ax.imshow(mat, extent=[x,x+w,y,y+h], aspect="auto", zorder=0, cmap=cm, alpha=0.2)
    ax.axis(lim)

colors = ["#CC5A43","#5375D4"]*3

data = {
    "year": [2004, 2022, 2004, 2022, 2004, 2022],
    "countries" : ["Sweden", "Sweden", "Denmark", "Denmark", "Norway", "Norway"],
    "sites": [13,15,4,10,5,8]
}
df= pd.DataFrame(data)

df['pct_change'] = df.groupby('countries', sort=True)['sites'].apply(
     lambda x: x.pct_change()).to_numpy()*-1
df['ctry_code'] = df.countries.astype(str).str[:2].astype(str).str.upper()
df = df.sort_values(['countries','year'], ascending=True ).reset_index(drop=True)
df['diff'] = df.groupby(['countries'])['sites'].diff()
df['diff'].fillna(df.sites, inplace=True)
countries = df.countries.unique()
code = df.ctry_code.unique()
pct_change = df.pct_change

x_coord = df.groupby('countries')['diff'].apply(lambda x: x.values) #convert the columns into numpy 2D array

fig, ax = plt.subplots(figsize=(6,5), facecolor = "#FFFFFF")

# use a colormap
cmap = plt.cm.RdBu

bars = []

for i, (color, x_c, country) in enumerate(zip(colors,x_coord, countries)):
    bar = ax.broken_barh([x_c], (i-0.2,0.4),facecolors=cmap(0.7),alpha= 0.2)
    bars.append(bar)
    
gradientbars(bars, ax)
    
ax.scatter( df.sites, df.countries, marker="D", s=3000, color = colors)

ax.set(xlim=[0, 16], ylim=[-1, 3])

ax.xaxis.set_ticks(np.arange(0,20,5),labels = [0,5,10,15])
ax.tick_params(axis="x", which="major",length=0,labelsize=14,colors= '#C8C9C9')

# Major ticks every 20, minor ticks every 5
major_ticks = np.arange(0, 16, 1)
ax.set_xticks(major_ticks)
ax.grid(which='major', axis='x', linestyle='-', alpha=0.4, color = "#C8C9C9")
ax.set_axisbelow(True)
plt.yticks([])
plt.box(False)


labels = ['2004','2022']
colors = ["#5375D4","#CC5A43",]
lines = [Line2D([0], [0], color=c,  marker='D',linestyle='', markersize=25,) for c in colors]
leg = ax.get_legend()
plt.figlegend( lines,labels,
           labelcolor="#C8C9C9",
           bbox_to_anchor=(0.3, 0.00), loc="lower center",
            ncols = 2,frameon=False, fontsize= 25)

这将为您提供以下结果:

enter image description here

Python相关问答推荐

线性模型PanelOLS和statmodels OLS之间的区别

Python多处理:当我在一个巨大的pandas数据框架上启动许多进程时,程序就会陷入困境

_repr_html_实现自定义__getattr_时未显示

在Polars(Python库)中将二进制转换为具有非UTF-8字符的字符串变量

如何从在虚拟Python环境中运行的脚本中运行需要宿主Python环境的Shell脚本?

将pandas Dataframe转换为3D numpy矩阵

使用groupby Pandas的一些操作

多处理队列在与Forking http.server一起使用时随机跳过项目

如何更改groupby作用域以找到满足掩码条件的第一个值?

手动设置seborn/matplotlib散点图连续变量图例中显示的值

从旋转的DF查询非NaN值

将一个双框爆炸到另一个双框的范围内

在numpy数组中寻找楼梯状 struct

如何重新组织我的Pandas DataFrame,使列名成为列值?

如何在Python中解析特定的文本,这些文本包含了同一行中的所有内容,

将数字数组添加到Pandas DataFrame的单元格依赖于初始化

递归链表反转与打印语句挂起

如何在表单中添加管理员风格的输入(PDF)

如何删除剪裁圆的对角线的外部部分

如何通过函数的强式路径动态导入函数?