我有一个包含两列的pandas数据框。其中一个列值需要映射到十六进制的颜色。另一个图形化过程从那里开始。
这是我到目前为止所尝试的。部分玩具代码取自here。
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
# Create dataframe
df = pd.DataFrame(np.random.randint(0,21,size=(7, 2)), columns=['some_value', 'another_value'])
# Add a nan to handle realworld
df.iloc[-1] = np.nan
# Try to map values to colors in hex
# # Taken from here
norm = matplotlib.colors.Normalize(vmin=0, vmax=21, clip=True)
mapper = plt.cm.ScalarMappable(norm=norm, cmap=plt.cm.viridis)
df['some_value_color'] = df['some_value'].apply(lambda x: mapper.to_rgba(x))
df
哪个输出:
如何一次性将'some_value'
df列值转换为十六进制?
理想情况下使用sns.cubehelix_palette(light=1)
我不反对使用matplotlib
提前致谢。
答案 0 :(得分:3)
您可以使用matplotlib.colors.to_hex()
将颜色转换为十六进制表示。
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import seaborn as sns
# Create dataframe
df = pd.DataFrame(np.random.randint(0,21,size=(7, 2)), columns=['some_value', 'another_value'])
# Add a nan to handle realworld
df.iloc[-1] = np.nan
# Try to map values to colors in hex
# # Taken from here
norm = matplotlib.colors.Normalize(vmin=0, vmax=21, clip=True)
mapper = plt.cm.ScalarMappable(norm=norm, cmap=plt.cm.viridis)
df['some_value_color'] = df['some_value'].apply(lambda x: mcolors.to_hex(mapper.to_rgba(x)))
df
<小时/>
以上方法易于使用,但可能效率不高。在接下来让我们比较一些替代方案。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
def create_df(n=10):
# Create dataframe
df = pd.DataFrame(np.random.randint(0,21,size=(n, 2)),
columns=['some_value', 'another_value'])
# Add a nan to handle realworld
df.iloc[-1] = np.nan
return df
以下是上述解决方案。它将逐行应用转换为数据帧。这效率很低。
def apply1(df):
# map values to colors in hex via
# matplotlib to_hex by pandas apply
norm = mcolors.Normalize(vmin=np.nanmin(df['some_value'].values),
vmax=np.nanmax(df['some_value'].values), clip=True)
mapper = plt.cm.ScalarMappable(norm=norm, cmap=plt.cm.viridis)
df['some_value_color'] = df['some_value'].apply(lambda x: mcolors.to_hex(mapper.to_rgba(x)))
return df
这就是为什么我们可能首先选择将值计算为numpy数组,然后将此数组指定为新创建的列。
def apply2(df):
# map values to colors in hex via
# matplotlib to_hex by assigning numpy array as column
norm = mcolors.Normalize(vmin=np.nanmin(df['some_value'].values),
vmax=np.nanmax(df['some_value'].values), clip=True)
mapper = plt.cm.ScalarMappable(norm=norm, cmap=plt.cm.viridis)
a = mapper.to_rgba(df['some_value'])
df['some_value_color'] = np.apply_along_axis(mcolors.to_hex, 1, a)
return df
最后,我们可以使用从matplotlib色图创建的查找表(LUT),并通过规范化数据索引LUT。由于此解决方案需要首先创建LUT,因此对于具有比LUT具有颜色的条目少的条目的数据帧而言,它是相当不可靠的,但是对于大型数据帧将获得回报。
def apply3(df):
# map values to colors in hex via
# creating a hex Look up table table and apply the normalized data to it
norm = mcolors.Normalize(vmin=np.nanmin(df['some_value'].values),
vmax=np.nanmax(df['some_value'].values), clip=True)
lut = plt.cm.viridis(np.linspace(0,1,256))
lut = np.apply_along_axis(mcolors.to_hex, 1, lut)
a = (norm(df['some_value'].values)*255).astype(np.int16)
df['some_value_color'] = lut[a]
return df
比较时间
我们来看一个10000行的数据帧。
df = create_df(10000)
原始解决方案(apply1)
%timeit apply1(df)
2.66 s per loop
数组解决方案(apply2)
%timeit apply2(df)
240 ms per loop
LUT解决方案(apply3)
%timeit apply1(df)
7.64 ms per loop
在这种情况下,LUT解决方案几乎可以提高400倍。