如何一次性将 df 列值映射到十六进制颜色?

Ita*_*vni 4 colors matplotlib python-3.x pandas

我有一个包含两列的熊猫数据框。列值之一需要映射到十六进制颜色。另一个绘图过程从那里接管。

这是我到目前为止所尝试的。部分玩具代码取自此处

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
Run Code Online (Sandbox Code Playgroud)

哪些输出:

在此处输入图片说明

如何'some_value' 一次性将df 列值转换为十六进制?理想情况下使用sns.cubehelix_palette(light=1)

我不反对使用除 matplotlib

提前致谢。

Imp*_*est 6

您可以使用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
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


效率

上面的方法很容易使用,但可能不是很有效。下面让我们比较一些替代方案。

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
Run Code Online (Sandbox Code Playgroud)

以下是上面的解决方案。它逐行将转换应用于数据帧。这相当低效。

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
Run Code Online (Sandbox Code Playgroud)

这就是为什么我们可能会选择首先将值计算到一个 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
Run Code Online (Sandbox Code Playgroud)

最后,我们可以使用从 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
Run Code Online (Sandbox Code Playgroud)

比较时间 让我们以一个包含 10000 行的数据帧为例。 df = create_df(10000)

在这种情况下,LUT 解决方案提供了近 400 倍的改进。