微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在python中将标量映射为颜色的快速方法

我正在寻找一种在python中将标量映射到十六进制颜色的快速方法

import matplotlib
import matplotlib.cm as cm
import matplotlib.colors as mcol

np.random.seed(0) 
df = pd.DataFrame(np.random.rand(20000,1))
df.head()

    0
0   0.548814
1   0.715189
2   0.602763
3   0.544883
4   0.423655

我只有20种颜色,所以我想知道matplotlib是最好的解决方案,还是简单的查找表会更好.

colors = ["#084594", "#0F529E", "#1760A8", "#1F6EB3", "#2979B9", "#3484BE", "#3E8EC4",
                "#4A97C9", "#57A0CE", "#64A9D3", "#73B2D7", "#83BBDB", "#93C4DE", "#A2CBE2",
                "#AED1E6", "#BBD6EB", "#C9DCEF", "#DBE8F4", "#EDF3F9", "#FFFFFF"]
values = df[0].values

@profile
def apply_method(): # 6.9 sec
    cm1 = mcol.ListedColormap(colors)
    norm = matplotlib.colors.normalize(vmin=np.min(values), vmax=np.max(values), clip=True)
    mapper = cm.ScalarMappable(norm=norm, cmap=cm1)

    return df[0].apply(lambda row: mcol.to_hex(mapper.to_rgba(row)))

%time apply_method()

从探查器中,我看到to_rgba()是最昂贵的方法(6.5 sec仅适用于20.000个值).

因此,我正在寻找一种绕过to_rgba()方法方法.有没有办法从cm.ScalarMappable获取颜色范围?然后查找正确的十六进制颜色?

解决方法:

问题代码中最昂贵的方法不是to_rgba(),而是DataFrame.apply,因为它将函数分别应用于每行.

我对这个问题的回答中给出了使用matplotlib颜色图的不同方法间的比较:How do I map df column values to hex color in one go?

精髓在于,使用查找表(LUT)确实要快得多(在那儿调查的情况下是系数400).

但是请注意,在此问题的情况下,根本不需要使用matplotlib.由于您已经有了十六进制格式的可能颜色列表,因此绝对不需要使用matplotlib并将十六进制颜色转换为颜色图,然后再转换回十六进制颜色.

相反,仅将颜色列表直接用作查找表(LUT)会更快.取一个具有10000个条目的数据框(以使其与其他答案的时间一致),此问题的代码花费2.7秒.

以下代码需要380 µs.这是7000改善的一个因素.
链接问题答案为7.7 ms的使用matplotlib的最佳方法相比,它仍然要好20倍.

import numpy as np; np.random.seed(0)
import pandas as pd

def create_df(n=10000):
    return pd.DataFrame(np.random.rand(n,1), columns=['some_value'])

def apply(df):
    colors = ["#084594", "#0F529E", "#1760A8", "#1F6EB3", "#2979B9", "#3484BE", "#3E8EC4",
              "#4A97C9", "#57A0CE", "#64A9D3", "#73B2D7", "#83BBDB", "#93C4DE", "#A2CBE2",
              "#AED1E6", "#BBD6EB", "#C9DCEF", "#DBE8F4", "#EDF3F9", "#FFFFFF"]
    colors = np.array(colors)
    v = df['some_value'].values
    v = ((v-v.min())/(v.max()-v.min())*(len(colors)-1)).astype(np.int16)
    return pd.Series(colors[v])

df = create_df()
%timeit apply(df)

# 376 µs

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐