Стилизация
Новое в версии 0.17.1
Предварительная версия: Эта функция новая и все еще находится в разработке. Мы будем добавлять новые функции и, возможно, вносить несовместимые изменения в будущих выпусках. Мы будем рады получить ваши отзывы.
Этот документ написан в формате Jupyter Notebook и может быть просмотрен или загружен здесь.
Вы можете применить условную стилизацию, визуальную стилизацию DataFrame в зависимости от данных внутри, используя свойство DataFrame.style. Это свойство возвращает объект Styler, который имеет полезные методы для форматирования и отображения DataFrames.
Стилизация выполняется с помощью CSS. Вы пишете «функции стилизации», которые принимают скаляры, DataFrame или Series, и возвращают индексированные DataFrame или Series с парами атрибутов CSS "attribute: value" для значений. Эти функции могут быть поэтапно переданы в Styler, который собирает стили перед отрисовкой.
Создание стилей
Передайте свои функции стилизации в один из следующих методов:
-
Styler.applymap: поэлементно -
Styler.apply: по столбцам/строкам/таблице
Оба метода принимают функцию (и некоторые другие ключевые аргументы) и применяют вашу функцию к DataFrame определенным образом. Styler.applymap обрабатывает DataFrame поэлементно. Styler.apply передает каждый столбец или строку в ваш DataFrame по одному или всю таблицу целиком, в зависимости от ключевого аргумента axis. Для столбцов используйте axis=0, для строк axis=1, и для всей таблицы целиком axis=None.
Для Styler.applymap ваша функция должна принимать скаляр и возвращать строку с парой атрибут-значение CSS.
Для Styler.apply ваша функция должна принимать Series или DataFrame (в зависимости от параметра axis) и возвращать Series или DataFrame с одинаковой формой, где каждое значение — это строка с парой атрибут-значение CSS.
Давайте рассмотрим несколько примеров.
[2]:
import pandas as pd
import numpy as np
np.random.seed(24)
df = pd.DataFrame({'A': np.linspace(1, 10, 10)})
df = pd.concat([df, pd.DataFrame(np.random.randn(10, 4), columns=list('BCDE'))],
axis=1)
df.iloc[0, 2] = np.nan
Вот пример рендеринга DataFrame, без стилей:
[3]:
df.style
[3]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Примечание: Атрибут DataFrame.style — свойство, которое возвращает объект Styler. У Styler определён метод _repr_html_, поэтому они отображаются автоматически. Если вам нужно получить исходный HTML для дальнейшей обработки или записи в файл, вызовите метод .render(), который возвращает строку.
Вышеприведённый вывод очень похож на стандартное HTML-представление DataFrame. Но мы сделали некоторую работу за кулисами, чтобы прикрепить CSS-классы к каждой ячейке. Их можно просмотреть, вызвав метод .render.
[4]:
df.style.highlight_null().render().split('\n')[:10]
[4]:
['<style type="text/css" >',
' #T_acfc12d6_a988_11e9_a75e_31802e421a9brow0_col2 {',
' background-color: red;',
' }</style><table id="T_acfc12d6_a988_11e9_a75e_31802e421a9b" ><thead> <tr> <th class="blank level0" ></th> <th class="col_heading level0 col0" >A</th> <th class="col_heading level0 col1" >B</th> <th class="col_heading level0 col2" >C</th> <th class="col_heading level0 col3" >D</th> <th class="col_heading level0 col4" >E</th> </tr></thead><tbody>',
' <tr>',
' <th id="T_acfc12d6_a988_11e9_a75e_31802e421a9blevel0_row0" class="row_heading level0 row0" >0</th>',
' <td id="T_acfc12d6_a988_11e9_a75e_31802e421a9brow0_col0" class="data row0 col0" >1</td>',
' <td id="T_acfc12d6_a988_11e9_a75e_31802e421a9brow0_col1" class="data row0 col1" >1.32921</td>',
' <td id="T_acfc12d6_a988_11e9_a75e_31802e421a9brow0_col2" class="data row0 col2" >nan</td>',
' <td id="T_acfc12d6_a988_11e9_a75e_31802e421a9brow0_col3" class="data row0 col3" >-0.31628</td>']
row0_col2 — идентификатор этой конкретной ячейки. Мы также добавили уникальный UUID к каждому идентификатору строки/столбца для каждого DataFrame, чтобы стили одного не конфликтовали со стилями другого в одном и том же блокноте или на одной странице (вы можете установить uuid, чтобы связать стили двух DataFrames).
При написании функций стилей вы сами заботитесь о создании пар атрибутов/значений CSS, которые вам нужны. Pandas сопоставляет их с CSS-классами, идентифицирующими каждую ячейку.
Давайте напишем простую функцию стилей, которая будет окрашивать отрицательные числа в красный цвет, а положительные — в чёрный.
[5]:
def color_negative_red(val):
"""
Takes a scalar and returns a string with
the css property `'color: red'` for negative
strings, black otherwise.
"""
color = 'red' if val < 0 else 'black'
return 'color: %s' % color
В этом случае стиль ячейки зависит только от её значения. Это означает, что мы должны использовать метод Styler.applymap, который работает поэлементно.
[6]:
s = df.style.applymap(color_negative_red) s
[6]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Обратите внимание на сходство со стандартным df.applymap, который работает с элементами DataFrames. Мы хотим, чтобы вы могли повторно использовать свои существующие знания о взаимодействии с DataFrames.
Также обратите внимание, что наша функция возвращает строку, содержащую атрибут CSS и его значение, разделенные двоеточием, как и в теге <style>. Это будет общей темой.
Наконец, формы ввода совпали. Styler.applymap вызывает функцию для каждого скалярного ввода, и функция возвращает скалярный вывод.
Теперь предположим, что вы хотите выделить максимальное значение в каждом столбце. Мы больше не можем использовать .applymap , так как оно работало с элементами. Вместо этого мы обратимся к .apply, которое работает по столбцам (или по строкам с использованием ключевого слова axis). Позже мы увидим, что что-то вроде highlight_max уже определено в Styler, поэтому вам не нужно будет это писать самостоятельно.
[7]:
def highlight_max(s):
'''
highlight the maximum in a Series yellow.
'''
is_max = s == s.max()
return ['background-color: yellow' if v else '' for v in is_max]
[8]:
df.style.apply(highlight_max)
[8]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
В этом случае входные данные представляют собой Series, по одному столбцу за раз. Обратите внимание, что выходная форма highlight_max соответствует входной форме, массиву с len(s) элементами.
Мы рекомендуем использовать цепочки методов для поэтапного построения стиля, прежде чем окончательно отобразить его в конце цепочки.
[9]:
df.style.\
applymap(color_negative_red).\
apply(highlight_max)
[9]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Выше мы использовали Styler.apply для передачи каждого столбца по одному.
Совет по отладке: если у вас возникли проблемы с написанием функции стиля, попробуйте просто передать её в DataFrame.apply. Внутри Styler.apply используется DataFrame.apply, поэтому результат должен быть одинаковым.
А что, если вы хотите выделить только максимальное значение во всей таблице? Используйте .apply(function, axis=None) для указания того, что ваша функция хочет всю таблицу, а не один столбец или строку за раз. Попробуем это дальше.
Мы перепишем наш highlight-max для обработки либо Series (из .apply(axis=0 or 1)) или DataFrame (из .apply(axis=None)). Мы также добавим возможность регулировать цвет, чтобы продемонстрировать, что .apply, и .applymap передают ключевые аргументы.
[10]:
def highlight_max(data, color='yellow'):
'''
highlight the maximum in a Series or DataFrame
'''
attr = 'background-color: {}'.format(color)
if data.ndim == 1: # Series from .apply(axis=0) or axis=1
is_max = data == data.max()
return [attr if v else '' for v in is_max]
else: # from .apply(axis=None)
is_max = data == data.max().max()
return pd.DataFrame(np.where(is_max, attr, ''),
index=data.index, columns=data.columns)
При использовании Styler.apply(func, axis=None), функция должна возвращать DataFrame с теми же индексами и метками столбцов.
[11]:
df.style.apply(highlight_max, color='darkorange', axis=None)
[11]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Резюме стилей построения
Функции стилей должны возвращать строки с одним или несколькими CSS attribute: value разделенными точкой с запятой. Используйте
-
Styler.applymap(func)для стилей на уровне элементов -
Styler.apply(func, axis=0)для стилей на уровне столбцов -
Styler.apply(func, axis=1)для стилей на уровне строк -
Styler.apply(func, axis=None)для стилей на уровне таблицы
И, что очень важно, входные и выходные формы func должны совпадать. Если x - это вход, то func(x).shape == x.shape.
Более тонкий контроль: срезы
И Styler.apply, и Styler.applymap принимают subset ключевое слово. Это позволяет применять стили к определённым строкам или столбцам, без необходимости кодирования этой логики в вашу style функцию.
Значение, переданное subset, ведет себя аналогично срезу DataFrame.
- Скаляр обрабатывается как метка столбца
- Список (или ряд или массив NumPy)
- Кортеж обрабатывается как
(row_indexer, column_indexer)
Рекомендуется использовать pd.IndexSlice для построения кортежа в последнем случае.
[12]:
df.style.apply(highlight_max, subset=['B', 'C', 'D'])
[12]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Для среза строк и столбцов подойдёт любой допустимый индексатор для .loc.
[13]:
df.style.applymap(color_negative_red,
subset=pd.IndexSlice[2:5, ['B', 'D']])
[13]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
В настоящее время поддерживается только выборка по меткам, а не по позициям.
Если ваша функция стиля использует ключевое слово subset или axis, рассмотрите возможность обернуть вашу функцию в functools.partial, частично исключив это ключевое слово.
my_func2 = functools.partial(my_func, subset=42)
Более тонкий контроль: отображение значений
Мы различаем значение отображения и значение фактического значения в Styler. Чтобы контролировать значение отображения, текст печатается в каждой ячейке, используйте Styler.format. Ячейки могут быть отформатированы в соответствии со строкой формата спецификации или вызываемым объектом, который принимает одно значение и возвращает строку.
[14]:
df.style.format("{:.2%}")
[14]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 100.00% | 132.92% | nan% | -31.63% | -99.08% |
| 1 | 200.00% | -107.08% | -143.87% | 56.44% | 29.57% |
| 2 | 300.00% | -162.64% | 21.96% | 67.88% | 188.93% |
| 3 | 400.00% | 96.15% | 10.40% | -48.12% | 85.02% |
| 4 | 500.00% | 145.34% | 105.77% | 16.56% | 51.50% |
| 5 | 600.00% | -133.69% | 56.29% | 139.29% | -6.33% |
| 6 | 700.00% | 12.17% | 120.76% | -0.20% | 162.78% |
| 7 | 800.00% | 35.45% | 103.75% | -38.57% | 51.98% |
| 8 | 900.00% | 168.66% | -132.60% | 142.90% | -208.94% |
| 9 | 1000.00% | -12.98% | 63.15% | -58.65% | 29.07% |
Используйте словарь для форматирования конкретных столбцов.
[15]:
df.style.format({'B': "{:0<4.0f}", 'D': '{:+.2f}'})
[15]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1000 | nan | -0.32 | -0.99081 |
| 1 | 2 | -100 | -1.43871 | +0.56 | 0.295722 |
| 2 | 3 | -200 | 0.219565 | +0.68 | 1.88927 |
| 3 | 4 | 1000 | 0.104011 | -0.48 | 0.850229 |
| 4 | 5 | 1000 | 1.05774 | +0.17 | 0.515018 |
| 5 | 6 | -100 | 0.562861 | +1.39 | -0.063328 |
| 6 | 7 | 0000 | 1.2076 | -0.00 | 1.6278 |
| 7 | 8 | 0000 | 1.03753 | -0.39 | 0.519818 |
| 8 | 9 | 2000 | -1.32596 | +1.43 | -2.08935 |
| 9 | 10 | -000 | 0.631523 | -0.59 | 0.29072 |
Или передайте вызываемый объект (или словарь вызываемых объектов) для более гибкого управления.
[16]:
df.style.format({"B": lambda x: "±{:.2f}".format(abs(x))})
[16]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | ±1.33 | nan | -0.31628 | -0.99081 |
| 1 | 2 | ±1.07 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | ±1.63 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | ±0.96 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | ±1.45 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | ±1.34 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | ±0.12 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | ±0.35 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | ±1.69 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | ±0.13 | 0.631523 | -0.586538 | 0.29072 |
Встроенные стили
Наконец, мы ожидаем, что определённые функции стилизации будут достаточно распространёнными, и включили несколько «встроенных» в Styler, так что вам не придётся писать их самим.
[17]:
df.style.highlight_null(null_color='red')
[17]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Вы можете создать «карты теплоты» с помощью метода background_gradient. Для этого потребуются matplotlib, и мы будем использовать Seaborn для получения красивой цветовой карты.
[18]:
import seaborn as sns
cm = sns.light_palette("green", as_cmap=True)
s = df.style.background_gradient(cmap=cm)
s
/opt/conda/envs/pandas/lib/python3.7/site-packages/matplotlib/colors.py:479: RuntimeWarning: invalid value encountered in less
xa[xa < 0] = -1
[18]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Styler.background_gradient принимает именованные аргументы low и high. Грубо говоря, они расширяют диапазон ваших данных на low и high процентов, чтобы при преобразовании цветов не использовался весь диапазон цветовой карты. Это полезно, чтобы текст оставался читаемым.
[19]:
# Uses the full color range df.loc[:4].style.background_gradient(cmap='viridis')
[19]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
[20]:
# Compress the color range
(df.loc[:4]
.style
.background_gradient(cmap='viridis', low=.5, high=0)
.highlight_null('red'))
[20]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
Также есть .highlight_min и .highlight_max.
[21]:
df.style.highlight_max(axis=0)
[21]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Используйте Styler.set_properties в случаях, когда стиль не зависит от значений.
[22]:
df.style.set_properties(**{'background-color': 'black',
'color': 'lawngreen',
'border-color': 'white'})
[22]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Диаграммы столбцов
Вы можете включить “диаграммы столбцов” в вашу таблицу DataFrame.
[23]:
df.style.bar(subset=['A', 'B'], color='#d65f5f')
[23]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
В версии 0.20.0 появилась возможность дальнейшей настройки столбчатой диаграммы: теперь вы можете выровнять df.style.bar по нулю или по середине значения (в дополнение к уже существующему способу выравнивания минимального значения слева ячейки), и вы можете передать список [color_negative, color_positive].
Вот как вы можете изменить вышеизложенное с помощью нового align='mid' параметра:
[24]:
df.style.bar(subset=['A', 'B'], align='mid', color=['#d65f5f', '#5fba7d'])
[24]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Следующий пример призван продемонстрировать поведение новых опций выравнивания:
[25]:
import pandas as pd
from IPython.display import HTML
# Test series
test1 = pd.Series([-100,-60,-30,-20], name='All Negative')
test2 = pd.Series([10,20,50,100], name='All Positive')
test3 = pd.Series([-10,-5,0,90], name='Both Pos and Neg')
head = """
<table>
<thead>
<th>Align</th>
<th>All Negative</th>
<th>All Positive</th>
<th>Both Neg and Pos</th>
</thead>
</tbody>
"""
aligns = ['left','zero','mid']
for align in aligns:
row = "<tr><th>{}</th>".format(align)
for serie in [test1,test2,test3]:
s = serie.copy()
s.name=''
row += "<td>{}</td>".format(s.to_frame().style.bar(align=align,
color=['#d65f5f', '#5fba7d'],
width=100).render()) #testn['width']
row += '</tr>'
head += row
head+= """
</tbody>
</table>"""
HTML(head)
[25]:
| Выравнивание | Все отрицательные | Все положительные | Отрицательные и положительные | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| left |
|
|
|
||||||||||||||||||||||||||||||
| zero |
|
|
|
||||||||||||||||||||||||||||||
| mid |
|
|
|
Применение стилей
Предположим, у вас есть привлекательный стиль для DataFrame, и теперь вы хотите применить тот же стиль к другому DataFrame. Экспортируйте стиль с помощью df1.style.export, и импортируйте его во второй DataFrame с помощью df1.style.set
[26]:
df2 = -df style1 = df.style.applymap(color_negative_red) style1
[26]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
[27]:
style2 = df2.style style2.use(style1.export()) style2
[27]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | -1 | -1.32921 | nan | 0.31628 | 0.99081 |
| 1 | -2 | 1.07082 | 1.43871 | -0.564417 | -0.295722 |
| 2 | -3 | 1.6264 | -0.219565 | -0.678805 | -1.88927 |
| 3 | -4 | -0.961538 | -0.104011 | 0.481165 | -0.850229 |
| 4 | -5 | -1.45342 | -1.05774 | -0.165562 | -0.515018 |
| 5 | -6 | 1.33694 | -0.562861 | -1.39285 | 0.063328 |
| 6 | -7 | -0.121668 | -1.2076 | 0.00204021 | -1.6278 |
| 7 | -8 | -0.354493 | -1.03753 | 0.385684 | -0.519818 |
| 8 | -9 | -1.68658 | 1.32596 | -1.42898 | 2.08935 |
| 9 | -10 | 0.12982 | -0.631523 | 0.586538 | -0.29072 |
Обратите внимание, что вы можете совместно использовать стили, даже если они зависят от данных. Стили переоцениваются в новом DataFrame, на который они use.
Другие варианты
Вы ознакомились с несколькими методами для стилизации данных. Styler также предлагает несколько других вариантов стилей, которые не зависят от данных.
- precision
- captions
- стили для всего столбца
- скрытие индекса или столбцов
Каждый из них можно указать двумя способами:
- Ключевой аргумент для
Styler.__init__ - Вызов одного из методов
.set_или.hide_, например,.set_captionили.hide_columns
Лучший способ зависит от контекста. Используйте конструктор Styler при создании многих стилизованных DataFrame, которые должны иметь общие свойства. Для интерактивного использования методы .set_ и .hide_ более удобны.
Точность
Вы можете контролировать точность чисел с плавающей точкой, используя стандартный параметр pandas display.precision.
[28]:
with pd.option_context('display.precision', 2):
html = (df.style
.applymap(color_negative_red)
.apply(highlight_max))
html
[28]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.3 | nan | -0.32 | -0.99 |
| 1 | 2 | -1.1 | -1.4 | 0.56 | 0.3 |
| 2 | 3 | -1.6 | 0.22 | 0.68 | 1.9 |
| 3 | 4 | 0.96 | 0.1 | -0.48 | 0.85 |
| 4 | 5 | 1.5 | 1.1 | 0.17 | 0.52 |
| 5 | 6 | -1.3 | 0.56 | 1.4 | -0.063 |
| 6 | 7 | 0.12 | 1.2 | -0.002 | 1.6 |
| 7 | 8 | 0.35 | 1 | -0.39 | 0.52 |
| 8 | 9 | 1.7 | -1.3 | 1.4 | -2.1 |
| 9 | 10 | -0.13 | 0.63 | -0.59 | 0.29 |
Или через set_precision метод.
[29]:
df.style\ .applymap(color_negative_red)\ .apply(highlight_max)\ .set_precision(2)
[29]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.3 | nan | -0.32 | -0.99 |
| 1 | 2 | -1.1 | -1.4 | 0.56 | 0.3 |
| 2 | 3 | -1.6 | 0.22 | 0.68 | 1.9 |
| 3 | 4 | 0.96 | 0.1 | -0.48 | 0.85 |
| 4 | 5 | 1.5 | 1.1 | 0.17 | 0.52 |
| 5 | 6 | -1.3 | 0.56 | 1.4 | -0.063 |
| 6 | 7 | 0.12 | 1.2 | -0.002 | 1.6 |
| 7 | 8 | 0.35 | 1 | -0.39 | 0.52 |
| 8 | 9 | 1.7 | -1.3 | 1.4 | -2.1 |
| 9 | 10 | -0.13 | 0.63 | -0.59 | 0.29 |
Установка точности влияет только на выводимое число; полные значения с высокой точностью всегда передаются в ваши функции стилей. Вы всегда можете использовать df.round(2).style, если предпочитаете округлять с самого начала.
Подписи
Регулярные подписи к таблицам могут быть добавлены несколькими способами.
[30]:
df.style.set_caption('Colormaps, with a caption.')\
.background_gradient(cmap=cm)
[30]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Стили таблиц
Следующий вариант — «стили таблиц». Это стили, которые применяются к таблице в целом, но не обращают внимания на данные. Некоторые стили, включая псевдоселекторы, такие как :hover, могут использоваться только таким образом.
[31]:
from IPython.display import HTML
def hover(hover_color="#ffff99"):
return dict(selector="tr:hover",
props=[("background-color", "%s" % hover_color)])
styles = [
hover(),
dict(selector="th", props=[("font-size", "150%"),
("text-align", "center")]),
dict(selector="caption", props=[("caption-side", "bottom")])
]
html = (df.style.set_table_styles(styles)
.set_caption("Hover to highlight."))
html
[31]:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
table_styles должен быть списком словарей. Каждый словарь должен иметь ключи selector и props. Значение для selector должно быть допустимым селектором CSS. Помните, что все стили уже прикреплены к id, уникальному для каждого Styler. Этот селектор дополняет id. Значение для props должно быть списком кортежей ('attribute', 'value').
table_styles чрезвычайно гибкие, но их не так приятно набирать вручную. Мы надеемся собрать некоторые полезные либо в pandas, либо, что предпочтительнее, в новом пакете, который базируется на этих инструментах.
Скрытие индекса или столбцов
Индекс можно скрыть при отрисовке, вызвав Styler.hide_index. Столбцы можно скрыть при отрисовке, вызвав Styler.hide_columns и передав имя столбца или срез столбцов.
[32]:
df.style.hide_index()
[32]:
| A | B | C | D | E |
|---|---|---|---|---|
| 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
[33]:
df.style.hide_columns(['C','D'])
[33]:
| A | B | E | |
|---|---|---|---|
| 0 | 1 | 1.32921 | -0.99081 |
| 1 | 2 | -1.07082 | 0.295722 |
| 2 | 3 | -1.6264 | 1.88927 |
| 3 | 4 | 0.961538 | 0.850229 |
| 4 | 5 | 1.45342 | 0.515018 |
| 5 | 6 | -1.33694 | -0.063328 |
| 6 | 7 | 0.121668 | 1.6278 |
| 7 | 8 | 0.354493 | 0.519818 |
| 8 | 9 | 1.68658 | -2.08935 |
| 9 | 10 | -0.12982 | 0.29072 |
CSS классы
К ячейкам прикреплены определённые CSS классы.
- Имена индексов и столбцов включают
index_nameиlevel<k>, гдеk— его уровень в многоуровневом индексе - Ячейки с метками индексов включают
row_heading-
row<n>, гдеn— числовая позиция строки -
level<k>, гдеk— уровень в многоуровневом индексе
- Ячейки с метками столбцов включают
col_heading-
col<n>, гдеn— числовая позиция столбца -
level<k>, гдеk— уровень в многоуровневом индексе
- Ячейки без данных включают
blank - Ячейки с данными включают
data
Ограничения
- Только для DataFrame
(use Series.to_frame().style) - Индекс и столбцы должны быть уникальными
- Нет большого представления, производительность невысока; предназначено для сводных DataFrame
- Можно стилизовать только значения, а не индекс или столбцы
- Можно только применять стили, нельзя вставлять новые HTML сущности
Некоторые из этих ограничений будут устранены в будущем.
Термины
- Функция стиля: функция, передаваемая в
Styler.applyилиStyler.applymapи возвращающая значения, такие как'css attribute: value' - Встроенные функции стиля: функции стиля, являющиеся методами в
Styler - Стиль таблицы: словарь с двумя ключами
selectorиprops.selector— CSS селектор, к которому будет примененоprops.props— список(attribute, value)кортежей. Список стилей таблицы передаётся вStyler.
Интересные примеры
Здесь представлены несколько интересных примеров.
Styler хорошо взаимодействует с виджетами. Если вы просматриваете это онлайн, а не запускаете блокнот самостоятельно, вы упускаете возможность интерактивного изменения цветовой палитры.
[34]:
from IPython.html import widgets
@widgets.interact
def f(h_neg=(0, 359, 1), h_pos=(0, 359), s=(0., 99.9), l=(0., 99.9)):
return df.style.background_gradient(
cmap=sns.palettes.diverging_palette(h_neg=h_neg, h_pos=h_pos, s=s, l=l,
as_cmap=True)
)
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
[35]:
def magnify():
return [dict(selector="th",
props=[("font-size", "4pt")]),
dict(selector="td",
props=[('padding', "0em 0em")]),
dict(selector="th:hover",
props=[("font-size", "12pt")]),
dict(selector="tr:hover td:hover",
props=[('max-width', '200px'),
('font-size', '12pt')])
]
[36]:
np.random.seed(25)
cmap = cmap=sns.diverging_palette(5, 250, as_cmap=True)
bigdf = pd.DataFrame(np.random.randn(20, 25)).cumsum()
bigdf.style.background_gradient(cmap, axis=1)\
.set_properties(**{'max-width': '80px', 'font-size': '1pt'})\
.set_caption("Hover to magnify")\
.set_precision(2)\
.set_table_styles(magnify())
[36]:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.23 | 1 | -0.84 | -0.59 | -0.96 | -0.22 | -0.62 | 1.8 | -2.1 | 0.87 | -0.92 | -0.23 | 2.2 | -1.3 | 0.076 | -1.2 | 1.2 | -1 | 1.1 | -0.42 | 2.3 | -2.6 | 2.8 | 0.68 | -1.6 |
| 1 | -1.7 | 1.6 | -1.1 | -1.1 | 1 | 0.0037 | -2.5 | 3.4 | -1.7 | 1.3 | -0.52 | -0.015 | 1.5 | -1.1 | -1.9 | -1.1 | -0.68 | -0.81 | 0.35 | -0.055 | 1.8 | -2.8 | 2.3 | 0.78 | 0.44 |
| 2 | -0.65 | 3.2 | -1.8 | 0.52 | 2.2 | -0.37 | -3 | 3.7 | -1.9 | 2.5 | 0.21 | -0.24 | -0.1 | -0.78 | -3 | -0.82 | -0.21 | -0.23 | 0.86 | -0.68 | 1.4 | -4.9 | 3 | 1.9 | 0.61 |
| 3 | -1.6 | 3.7 | -2.3 | 0.43 | 4.2 | -0.43 | -3.9 | 4.2 | -2.1 | 1.1 | 0.12 | 0.6 | -0.89 | 0.27 | -3.7 | -2.7 | -0.31 | -1.6 | 1.4 | -1.8 | 0.91 | -5.8 | 2.8 | 2.1 | 0.28 |
| 4 | -3.3 | 4.5 | -1.9 | -1.7 | 5.2 | -1 | -3.8 | 4.7 | -0.72 | 1.1 | -0.18 | 0.83 | -0.22 | -1.1 | -4.3 | -2.9 | -0.97 | -1.8 | 1.5 | -1.8 | 2.2 | -6.3 | 3.3 | 2.5 | 2.1 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5 | -0.84 | 4.2 | -1.7 | -2 | 5.3 | -0.99 | -4.1 | 3.9 | -1.1 | -0.94 | 1.2 | 0.087 | -1.8 | -0.11 | -4.5 | -0.85 | -2.1 | -1.4 | 0.8 | -1.6 | 1.5 | -6.5 | 2.8 | 2.1 | 3.8 |
| 6 | -0.74 | 5.4 | -2.1 | -1.1 | 4.2 | -1.8 | -3.2 | 3.8 | -3.2 | -1.2 | 0.34 | 0.57 | -1.8 | 0.54 | -4.4 | -1.8 | -4 | -2.6 | -0.2 | -4.7 | 1.9 | -8.5 | 3.3 | 2.5 | 5.8 |
| 7 | -0.44 | 4.7 | -2.3 | -0.21 | 5.9 | -2.6 | -1.8 | 5.5 | -4.5 | -3.2 | -1.7 | 0.18 | 0.11 | 0.036 | -6 | -0.45 | -6.2 | -3.9 | 0.71 | -3.9 | 0.67 | -7.3 | 3 | 3.4 | 6.7 |
| 8 | 0.92 | 5.8 | -3.3 | -0.65 | 6 | -3.2 | -1.8 | 5.6 | -3.5 | -1.3 | -1.6 | 0.82 | -2.4 | -0.4 | -6.1 | -0.52 | -6.6 | -3.5 | -0.043 | -4.6 | 0.51 | -5.8 | 3.2 | 2.4 | 5.1 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 9 | 0.38 | 5.5 | -4.5 | -0.8 | 7.1 | -2.6 | -0.44 | 5.3 | -2 | -0.33 | -0.8 | 0.26 | -3.4 | -0.82 | -6.1 | -2.6 | -8.5 | -4.5 | 0.41 | -4.7 | 1.9 | -6.9 | 2.1 | 3 | 5.2 |
| 10 | 2.1 | 5.8 | -3.9 | -0.98 | 7.8 | -2.5 | -0.59 | 5.6 | -2.2 | -0.71 | -0.46 | 1.8 | -2.8 | 0.48 | -6 | -3.4 | -7.8 | -5.5 | -0.7 | -4.6 | -0.52 | -7.7 | 1.5 | 5 | 5.8 |
| 11 | 1.9 | 4.5 | -2.2 | -1.4 | 5.9 | -0.49 | 0.017 | 5.8 | -1 | -0.6 | 0.49 | 2 | -1.5 | 1.9 | -5.9 | -4.5 | -8.2 | -3.4 | -2.2 | -4.3 | -1.2 | -7.9 | 1.4 | 5.3 | 5.8 |
| 12 | 3.2 | 4.2 | -3.1 | -2.3 | 5.9 | -2.6 | 0.33 | 6.7 | -2.8 | -0.2 | 1.9 | 2.6 | -1.5 | 0.75 | -5.3 | -4.5 | -7.6 | -2.9 | -2.2 | -4.8 | -1.1 | -9 | 2.1 | 6.4 | 5.6 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 13 | 2.3 | 4.5 | -3.9 | -2 | 6.8 | -3.3 | -2.2 | 8 | -2.6 | -0.8 | 0.71 | 2.3 | -0.16 | -0.46 | -5.1 | -3.8 | -7.6 | -4 | 0.33 | -3.7 | -1 | -8.7 | 2.5 | 5.9 | 6.7 |
| 14 | 3.8 | 4.3 | -3.9 | -1.6 | 6.2 | -3.2 | -1.5 | 5.6 | -2.9 | -0.33 | -0.97 | 1.7 | 3.6 | 0.29 | -4.2 | -4.1 | -6.7 | -4.5 | -2.2 | -2.4 | -1.6 | -9.4 | 3.4 | 6.1 | 7.5 |
| 15 | 5.6 | 5.3 | -4 | -2.3 | 5.9 | -3.3 | -1 | 5.7 | -3.1 | -0.33 | -1.2 | 2.2 | 4.2 | 1 | -3.2 | -4.3 | -5.7 | -4.4 | -2.3 | -1.4 | -1.2 | -11 | 2.6 | 6.7 | 5.9 |
| 16 | 4.1 | 4.3 | -2.4 | -3.3 | 6 | -2.5 | -0.47 | 5.3 | -4.8 | 1.6 | 0.23 | 0.099 | 5.8 | 1.8 | -3.1 | -3.9 | -5.5 | -3 | -2.1 | -1.1 | -0.56 | -13 | 2.1 | 6.2 | 4.9 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 5.6 | 4.6 | -3.5 | -3.8 | 6.6 | -2.6 | -0.75 | 6.6 | -4.8 | 3.6 | -0.29 | 0.56 | 5.8 | 2 | -2.3 | -2.3 | -5 | -3.2 | -3.1 | -2.4 | 0.84 | -13 | 3.6 | 7.4 | 4.7 |
| 18 | 6 | 5.8 | -2.8 | -4.2 | 7.1 | -3.3 | -1.2 | 7.9 | -4.9 | 1.4 | -0.63 | 0.35 | 7.5 | 0.87 | -1.5 | -2.1 | -4.2 | -2.5 | -2.5 | -2.9 | 1.9 | -9.7 | 3.4 | 7.1 | 4.4 |
| 19 | 4 | 6.2 | -4.1 | -4.1 | 7.2 | -4.1 | -1.5 | 6.5 | -5.2 | -0.24 | 0.0072 | 1.2 | 6.4 | -2 | -2.6 | -1.7 | -5.2 | -3.3 | -2.9 | -1.7 | 1.6 | -11 | 2.8 | 7.5 | 3.9 |
Экспорт в Excel
Новое в версии 0.20.0
Экспериментальная функция: Эта функция новая и находится в стадии разработки. В будущих версиях мы добавим новые функции и, возможно, внесём изменения, которые могут привести к нарушению работы. Мы с удовольствием рассмотрим ваши отзывы.
Некоторую поддержку экспорта стилизованных DataFrames в таблицы Excel предоставляют движки OpenPyXL или XlsxWriter. Обработанные свойства CSS2.2 включают:
background-color-
border-style,border-width,border-colorи их {top,right,bottom,leftварианты} colorfont-familyfont-stylefont-weighttext-aligntext-decorationvertical-alignwhite-space: nowrap- В настоящее время поддерживаются только именованные цвета CSS2 и шестнадцатеричные цвета в формате
#rgbили#rrggbb. - Для задания специфичных для Excel свойств стиля также доступны следующие псевдо-свойства CSS:
number-format
[37]:
df.style.\
applymap(color_negative_red).\
apply(highlight_max).\
to_excel('styled.xlsx', engine='openpyxl')
Скриншот вывода:
Расширяемость
Ядро pandas — это, и останется, его “высокопроизводительные, простые в использовании структуры данных”. С учётом этого, мы надеемся, что DataFrame.style достигнет двух целей:
- Предоставить API, приятный для интерактивного использования и “достаточно хороший” для многих задач
- Создать основу для специализированных библиотек, которые можно будет на ней построить
Если вы создадите на основе этого отличную библиотеку, сообщите нам, и мы добавим на неё ссылку.
Наследование
Если стандартный шаблон не совсем соответствует вашим потребностям, вы можете создать подкласс Styler и расширить или переопределить шаблон. Мы покажем пример расширения стандартного шаблона для вставки пользовательского заголовка перед каждой таблицей.
[38]:
from jinja2 import Environment, ChoiceLoader, FileSystemLoader from IPython.display import HTML from pandas.io.formats.style import Styler
Мы будем использовать следующий шаблон:
[39]:
with open("templates/myhtml.tpl") as f:
print(f.read())
{% extends "html.tpl" %}
{% block table %}
<h1>{{ table_title|default("My Table") }}</h1>
{{ super() }}
{% endblock table %}
Теперь, когда мы создали шаблон, нам нужно настроить подкласс Styler, который знает о нём.
[40]:
class MyStyler(Styler):
env = Environment(
loader=ChoiceLoader([
FileSystemLoader("templates"), # contains ours
Styler.loader, # the default
])
)
template = env.get_template("myhtml.tpl")
Обратите внимание, что мы включаем оригинальный загрузчик в загрузчик нашей среды. Это потому, что мы расширяем оригинальный шаблон, поэтому среде Jinja необходимо иметь возможность найти его.
Теперь мы можем использовать этот пользовательский стайлер. Это __init__ принимает DataFrame.
[41]:
MyStyler(df)
[41]:
Моя таблица
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Наш пользовательский шаблон принимает ключевое слово table_title. Мы можем указать значение в методе .render.
[42]:
HTML(MyStyler(df).render(table_title="Extending Example"))
[42]:
Расширение Примера
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Для удобства, мы предоставляем метод Styler.from_custom_template, который делает то же самое, что и пользовательский подкласс.
[43]:
EasyStyler = Styler.from_custom_template("templates", "myhtml.tpl")
EasyStyler(df)
[43]:
Моя таблица
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | 1 | 1.32921 | nan | -0.31628 | -0.99081 |
| 1 | 2 | -1.07082 | -1.43871 | 0.564417 | 0.295722 |
| 2 | 3 | -1.6264 | 0.219565 | 0.678805 | 1.88927 |
| 3 | 4 | 0.961538 | 0.104011 | -0.481165 | 0.850229 |
| 4 | 5 | 1.45342 | 1.05774 | 0.165562 | 0.515018 |
| 5 | 6 | -1.33694 | 0.562861 | 1.39285 | -0.063328 |
| 6 | 7 | 0.121668 | 1.2076 | -0.00204021 | 1.6278 |
| 7 | 8 | 0.354493 | 1.03753 | -0.385684 | 0.519818 |
| 8 | 9 | 1.68658 | -1.32596 | 1.42898 | -2.08935 |
| 9 | 10 | -0.12982 | 0.631523 | -0.586538 | 0.29072 |
Вот структура шаблона:
[44]:
with open("templates/template_structure.html") as f:
structure = f.read()
HTML(structure)
[44]:
<style type="text/css">
</style>
<table ...>
</table>
Подробности шаблона см. в репозитории GitHub.
© 2008–2012, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
Licensed under the 3-clause BSD License.
https://pandas.pydata.org/pandas-docs/version/0.25.0/user_guide/style.html