Как применить стиль к произвольному подмножеству кадра данных панд? В частности, у меня есть фрейм данных df, который содержит несколько NaN, и я хочу применить к нему градиент фона везде, кроме случаев, когда есть NaN (с одинаковой картой цветов, примененной ко всем ячейкам).

Я знаю, что background_gradientapplymap в более общем смысле) имеет параметр subset, но я не понимаю из документации, как его использовать для выбора произвольного подмножества кадра данных.

import numpy as np
import pandas as pd

df = pd.DataFrame(data={'A': [0, 1, np.nan], 'B': [.5, np.nan, 0], 'C': [np.nan, 1, 1]})
mask = ~pd.isnull(df)

Тогда если я попробую

df.style.background_gradient(subset=mask)

Я получаю сообщение об ошибке:

IndexingError: Too many indexers

Я знаю, как применить стиль в подмножество данных DataFrame в конкретном случае, когда это подмножество является декартовым продуктом индексов и столбцов, используя здесь что-то вроде решения: Как стиль подмножество панды dataframe?. Таким образом, вопрос в том, что делать, когда подмножество не является таким продуктом, как в примере выше.

Одним из решений может быть цикл по столбцам и применение стиля столбец за столбцом (тогда каждое приложение is к декартовому подмножеству продуктов). В моем случае я могу передать параметры low и high в метод background_gradient, чтобы сопоставить таблицы цветов между столбцами, но это не удается, когда (как указано выше) один или несколько из них столбцы содержат уникальное значение не NaN. Это, в свою очередь, можно обойти, переписав функцию background_gradient, но это явно нежелательно.

2
paul 24 Сен 2019 в 23:43

1 ответ

Лучший ответ

Вы можете написать собственную функцию для этого:

from matplotlib.cm import get_cmap
cmap = get_cmap('PuBu')

# update with low-high option
def threshold(x,low=0,high=1,mid=0.5):
    # nan cell
    if np.isnan(x): return ''

    # non-nan cell
    x = (x-low)/(high-low)
    background = f'background-color: rgba{cmap (x, bytes=True)}'
    text_color = f'color: white' if x > mid else ''
    return background+';'+text_color

# apply the style
df.style.applymap(threshold, low=-1, high=1, mid=0.3)

Выход:

enter image description here

3
Quang Hoang 24 Сен 2019 в 21:30