Стиль
Новое в версии 0.17.1
Предварительно: Эта функция новая и всё ещё находится в разработке. В будущих выпусках мы будем добавлять новые функции и, возможно, вносить несовместимые изменения. Мы будем рады вашим отзывам.
Этот документ написан как Jupyter Notebook и может быть просмотрен или скачан здесь.
Вы можете применить условную форматирование, визуальный стиль DataFrame в зависимости от данных внутри, используя свойство DataFrame.style. Это свойство возвращает объект Styler, который имеет полезные методы для форматирования и отображения DataFrame.
Стиль реализуется с помощью 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 (в зависимости от параметра оси) и возвращать 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(), который вернёт строку.
Вышеприведённый вывод очень похож на стандартное представление DataFrame в HTML. Но мы добавили CSS классы для каждой ячейки. Просмотреть их можно, вызвав метод .render.
[4]:
df.style.highlight_null().render().split('\n')[:10]
[4]:
['<style type="text/css" >',
' #T_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4frow0_col2 {',
' background-color: red;',
' }</style><table id="T_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4f" ><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_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4flevel0_row0" class="row_heading level0 row0" >0</th>',
' <td id="T_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4frow0_col0" class="data row0 col0" >1</td>',
' <td id="T_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4frow0_col1" class="data row0 col1" >1.32921</td>',
' <td id="T_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4frow0_col2" class="data row0 col2" >nan</td>',
' <td id="T_6acd6e3e_4518_11e9_bee3_b7bf1ae96e4frow0_col3" class="data row0 col3" >-0.31628</td>']
row0_col2 — идентификатор этой конкретной ячейки. Мы также добавили уникальный UUID к каждому идентификатору строки/столбца для каждого DataFrame, чтобы стили одного DataFrame не конфликтовали со стилями другого 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.6/site-packages/matplotlib/colors.py:512: 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]:
| Выравнивание | Все отрицательные | Все положительные | И отрицательные, и положительные | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| слева |
|
|
|
||||||||||||||||||||||||||||||
| ноль |
|
|
|
||||||||||||||||||||||||||||||
| середина |
|
|
|
Применение стилей
Предположим, у вас есть стили для 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 |
Обратите внимание, что вы можете обмениваться стилями, даже если они зависят от данных. Эти стили переоцениваются при применении к новым фреймам данных.
Другие параметры
Вы уже ознакомились с несколькими методами для стилизации данных. Также предоставляются несколько других вариантов стилей, которые не зависят от данных.
- точность
- подписи
- стили таблицы
- скрытие индекса или столбцов
Каждый из этих пунктов можно указать двумя способами:
- Аргумент ключевого слова для
- Вызов одного из методов или методов, например, или
Лучший метод зависит от контекста. Используйте конструктор, когда вы создаете много стилизованных фреймов данных, которые должны иметь общие свойства. Для интерактивного использования методы и более удобны.
Точность
Вы можете контролировать точность чисел с плавающей точкой, используя стандартный параметр pandas.
[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]:
My Table
| 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.24.2/user_guide/style.html