python-----DataFrame.style (三、切片)

如同Excel,在python中也可以使用条件格式(conditional formatting),使用DataFrame.style属性是格式化与展示的好方法,这个属性返回一个Styler 对象。

本文主要说说在使用相应的style函数时候如何使用切片,在官方文档中是这样描述的:

Both Styler.apply, and Styler.applymap accept a subset keyword. This
allows you to apply styles to specific rows or columns, without having
to code that logic into your style function.

The value passed to subset behaves similar to slicing a DataFrame.

A scalar is treated as a column label
A list (or series or numpy array) (is treated as a column label )
A tuple is treated as (row_indexer, column_indexer)

Consider using pd.IndexSlice to construct the tuple for the last one

In [12]:

df.style.apply(highlight_max, subset=['B', 'C', 'D'])

Out[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

For row and column slicing, any valid indexer to .loc will work

In [13]:

df.style.applymap(color_negative_red,
                  subset=pd.IndexSlice[2:5, ['B', 'D']])

Out[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

基本上表达的挺明白,但是遇到多级索引的情况下,文中并没有给出实例,我们进行实例演练:

# hierarchical indices and columns
index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]],
                                   names=['year', 'visit'])
columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']],
                                     names=['subject', 'type'])

# mock some data
data = np.round(np.random.randn(4, 6), 1)
data[:, ::2] *= 10
data += 37

# create the DataFrame
health_data = pd.DataFrame(data, index=index, columns=columns)
health_data

python-----DataFrame.style (三、切片)_第1张图片

现在我们想对一级行索引为2的行进行标红:
从上面的官方文档中给出的subset的三种方式中,最后一种方式符合我们的需求。

#先定义格式函数:
def row1_red(val): 
    return 'color:Magenta'

关键的问题在于如何正确的使用多级索引来达到我们的目的,先试一个,
在元组中使用切片将会导致语法错误:

health_data.style.applymap(row1_red,subset=[(:,2),])

    File "", line 1
        health_data.style.applymap(row1_red,subset=[(:,2),])
                                                     ^
    SyntaxError: invalid syntax

可以通过显示使用Python内置的slice()函数构建期望的切片来绕过上面的限制。但更好的办法是使用IndexSlice对象,它是Pandas专门用来处理这种情形的。

而原文中也说了:
Consider using pd.IndexSlice to construct the tuple for the last one.

我们用pd.IndexSlice试一下,先单独对于数据集health_data使用:

health_data.loc[pd.IndexSlice[:,2],]

python-----DataFrame.style (三、切片)_第2张图片
可见确实达到了效果

health_data.loc[pd.IndexSlice[:,2],:]

第二个位置写不写冒号都可以。

现在,我们用于Style属性:

health_data.style.applymap(row1_red,subset=(pd.IndexSlice[:,2],))

python-----DataFrame.style (三、切片)_第3张图片
perfect,但是要注意两点:
1、我们给subset传递的是个元组;
2、跟直接用于DataFrame.loc中不一样,subset中元组的第二个参数直接空即可,如果写冒号,反而会报错:
python-----DataFrame.style (三、切片)_第4张图片

甚至可以这样写:

health_data.style.applymap(row1_red,subset=pd.IndexSlice[pd.IndexSlice[:,2],:])

pd.IndexSlice也是比较灵活,但有时候也难以捉摸,有时间还是需要好好研究一下。

最后注意一个问题,在使用pd.IndexSlice时,只支持.loc,不支持.iloc.

Only label-based slicing is supported right now, not positional.

参考链接:
http://pandas.pydata.org/pandas-docs/stable/style.html
https://www.jianshu.com/p/342c81e89b98

你可能感兴趣的:(python,style,切片)