我有一个包含3列的数据框。我将df ['name']用作x轴,并将df ['value1']用作y轴。我想使用第3列(df ['value2'])为小节图生成颜色渐变。
正在使用的数据
df ['name']是名称。 df ['value1']是主要度量。 df ['value2']是df ['value1']值的置信度。我认为以颜色渐变显示df ['value2']会产生强大的视觉效果。
问题
我已经尝试了多种方法来使用matplotlib.colors模块实现此目的,但是没有任何结果产生我想要的结果。这是代码的基础(没有颜色映射到df ['value2'])。
INPUT
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import matplotlib.colors as colors
df = {'name': ['a','b','c','d'], 'value1': [10.1,13.3,9.5,15.1], 'value2': [1.5,2.0,3.5,1.3]}
df = pd.DataFrame(df)
print(df)
colorbar_1 = LinearSegmentedColormap.from_list('colorbar', ['#990000','#FF6666'], N=100)
df[['name','value1']].plot(kind='bar', colormap=colorbar_1 ,width=0.8, ylim=[9,16], fontsize=5)
plt.xticks(df.index,df['name'].values, rotation=90)
plt.ylim([9,16])
plt.gcf().subplots_adjust(bottom=0.15)
plt.tight_layout()
plt.savefig('test.png',dpi=600)
plt.show()
输出
name value1 value2
0 a 10.1 1.5
1 b 13.3 2.0
2 c 9.5 3.5
3 d 15.1 1.3
所需格式
[
我还用生成的十六进制代码生成了第四列,可用于执行手头的任务。我假设有合并df ['value2']的简便方法,但是生成十六进制代码可能很方便?
INPUT
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import matplotlib.colors as colors
df = {'name': ['a','b','c','d'], 'value1': [10.1,13.3,9.5,15.1], 'value2': [1.5,2.0,3.5,1.3]}
df = pd.DataFrame(df)
print(df)
norm = mpl.colors.Normalize(vmin=0, vmax=16, clip=True)
mapper = plt.cm.ScalarMappable(norm=norm, cmap=plt.cm.viridis)
df['hex_code'] = df['value2'].apply(lambda x: colors.to_hex(mapper.to_rgba(x)))
print(df)
输出
name value1 value2
0 a 10.1 1.5
1 b 13.3 2.0
2 c 9.5 3.5
3 d 15.1 1.3
name value1 value2 hex_code
0 a 10.1 1.5 #482374
1 b 13.3 2.0 #472d7b
2 c 9.5 3.5 #3e4989
3 d 15.1 1.3 #481d6f
问题之一是,使用df[['name', 'value1']].plot
会使大熊猫认为您要在数据帧中每行放置两根柱,一根柱用于“名称”,一根柱用于“ value1”。然后,大熊猫感到困惑,因为它无法为“名称”划定一个标准,因此跳过了这些。然后,对于color=
参数,pandas现在认为颜色列表中的第一种颜色用于“名称”,第二种颜色用于“ value1”。
因此,开始时,您需要将其称为df['value1'].plot()
。然后,熊猫真的很喜欢在x轴上使用索引。要将“名称”作为索引,只需使其成为数据框的索引即可。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, LinearSegmentedColormap, Normalize
df = {'name': ['a','b','c','d'], 'value1': [10.1,13.3,9.5,15.1], 'value2': [1.5,2.0,3.5,1.3]}
df = pd.DataFrame(df)
df.set_index('name', inplace=True)
print(df)
colormap_1 = LinearSegmentedColormap.from_list('colorbar', ['#990000','#FF6666'], N=100)
norm = Normalize(vmin=min(df['value2']), vmax=max(df['value2']))
colors = [colormap_1(norm(v)) for v in df['value2']]
df['value1'].plot(kind='bar', color=colors, width=0.8, ylim=[9,16], fontsize=5)
plt.xticks(rotation=90)
plt.ylim([9,16])
plt.tight_layout()
plt.savefig('test.png',dpi=600)
plt.show()
PS:要获得类似于链接图像的内容(因此不使用'value2',可以尝试:]
# same dataframe as before, with 'name' as index
ymin = 9
ymax = 16
barplot = df['value1'].plot(kind='bar', width=0.8, ylim=[ymin, ymax], fontsize=5)
plt.xticks(rotation=90)
gradient = np.linspace(1,0,256).reshape(256,1)
for bar in barplot.containers[0]:
bar.set_facecolor("none")
x, y = bar.get_xy()
w, h = bar.get_width(), bar.get_height()
plt.imshow(gradient, extent=[x, x + w, y + ymin, y + h], aspect="auto", cmap='bone')
plt.imshow(gradient, extent=[*plt.xlim(), *plt.ylim()] ,aspect="auto", cmap='copper_r', zorder=-1)
plt.tight_layout()
#plt.savefig('test.png',dpi=600)
plt.show()