Useful tricks

  1. 自定义pandas选项,设置

  2. 实用pandas中testing模块构建测试数据

  3. 巧用accessor接口方法

  4. 合并其他列拼接DatetimeIndex

  5. 使用分类数据(Categorical Data)节省时间和空间

  6. 利用Mapping巧妙实现映射

  7. 压缩pandas对象

  8. 源码及GitHub地址

1. 自定义pandas选项,设置

首先,大家可能不知道,pandas里面有一个方法pd.set_option(),利用它我们可以改变一些pandas中默认的核心设置, 从而适应我们自身的需要,开始前还是老样子,让我们先导入numpy和pandas包

import numpy as np
import pandas as pd
f'Using {pd.__name__}, Version {pd.__version__}'

现在让我们编写一个start方法来实现自定义pandas设置

def start():
    options = {
        'display': {
            'max_columns': None,
            'max_colwidth': 25,
            'expand_frame_repr': False,  
            'max_rows': 14,
            'max_seq_items': 50,         
            'precision': 4,
            'show_dimensions': False
        },
        'mode': {
            'chained_assignment': None   
        }
    }

    for category, option in options.items():
        for op, value in option.items():
            pd.set_option(f'{category}.{op}', value)  

if __name__ == '__main__':
    start()
    del start  

大家可以发现,我们在方法的最后调用了pandas的set_option方法,直接利用我们自定义的参数替代了原有的pandas参数,现在让我们测试一下:

可以发现max_rows 已经被替换成了我们设置的14,现在用一个真实的例子,我们利用一组公开的鲍鱼各项指标的数据来实验,数据源来自机器学习平台的公开数据

sex

length

diam

height

weight

rings

0

M

0.455

0.365

0.095

0.5140

15

1

M

0.350

0.265

0.090

0.2255

7

2

F

0.530

0.420

0.135

0.6770

9

3

M

0.440

0.365

0.125

0.5160

10

4

I

0.330

0.255

0.080

0.2050

7

5

I

0.425

0.300

0.095

0.3515

8

6

F

0.530

0.415

0.150

0.7775

20

...

...

...

...

...

...

...

4170

M

0.550

0.430

0.130

0.8395

10

4171

M

0.560

0.430

0.155

0.8675

8

4172

F

0.565

0.450

0.165

0.8870

11

4173

M

0.590

0.440

0.135

0.9660

10

4174

M

0.600

0.475

0.205

1.1760

9

4175

F

0.625

0.485

0.150

1.0945

10

4176

M

0.710

0.555

0.195

1.9485

12

我们可以看到,数据截断为14行,保留了小数点后4位小数作为精度,和我们刚刚设置的precision=4是一样的

2. testing模块构建测试数据

通过pandas.util.testing提供的方法,我们可以很容易的通过几行代码就构建出一个简单的测试数据类型,比如我们现在构建一个DataTime类型的数据,时间间隔为月:

A

B

C

2000-01-31

0.3574

-0.8804

0.2669

2000-02-29

0.3775

0.1526

-0.4803

2000-03-31

1.3823

0.2503

0.3008

2000-04-30

1.1755

0.0785

-0.1791

2000-05-31

-0.9393

-0.9039

1.1837

瞎生成一组乱七八糟的数据:

A

B

C

nTLGGTiRHF

-0.6228

0.6459

0.1251

WPBRn9jtsR

-0.3187

-0.8091

1.1501

7B3wWfvuDA

-1.9872

-1.0795

0.2987

yJ0BTjehH1

0.8802

0.7403

-1.2154

0luaYUYvy1

-0.9320

1.2912

-0.2907

关于可以随机生成的数据类型, 一共大概有30多种,大家如果感兴趣可以多试试:

这样我们如果有测试的需求,会很容易地构建相对应的假数据来测试。

3. 巧用accessor接口方法

accessor(访问器) 具体就是类似getter和setter,当然,Python里面不提倡存在setter和getter方法,但是这样可以便于大家理解,pandas Series类型有3类accessor:

  • .cat用于分类数据,

  • .str用于字符串(对象)数据,

  • .dt用于类似日期时间的数据。

让我们从.str开始看:假设现在我们有一些原始的城市/州/ 邮编数据作为Dataframe的一个字段:

如果我们想把每一行分成城市,州,邮编分开,可以用正则;

city

state

zip

0

Washington

DC

20003

1

Brooklyn

NY

11211-1755

2

Omaha

NE

68154

3

Pittsburgh

PA

15211

第二个访问器.dt用于类似日期时间的数据。它其实属于Pandas的DatetimeIndex,如果在Series上调用,它首先转换为DatetimeIndex

最后有关.cat访问器我们会在第5个技巧中提到

4. 合并其他列拼接DatetimeIndex

现在先让我们构建一个包含时间类型数据的Dataframe:

year

month

day

data

0

2017

1

1

-0.0767

1

2017

1

2

-1.2798

2

2017

1

3

0.4032

3

2017

2

1

1.2377

4

2017

2

2

-0.2060

5

2017

2

3

0.6187

6

2016

1

1

2.3786

7

2016

1

2

-0.4730

8

2016

1

3

-2.1505

9

2016

2

1

-0.6340

10

2016

2

2

0.7964

11

2016

2

3

0.0005

我们可以发现year,month,day是分开的三列,我们如果想要把它们合并为完整的时间并作为df的索引,可以这么做:

year

month

day

data

2017-01-01

2017

1

1

-0.0767

2017-01-02

2017

1

2

-1.2798

2017-01-03

2017

1

3

0.4032

2017-02-01

2017

2

1

1.2377

2017-02-02

2017

2

2

-0.2060

我们可以扔掉没用的列并把这个df压缩为Series:

5. 使用分类数据(Categorical Data)节省时间和空间

刚刚我们在第3个技巧的时候提到了访问器,现在让我们来看最后一个.cat

pandas中Categorical这个数据类型非常强大,通过类型转换可以让我们节省变量在内存占用的空间,提高运算速度,不过有关具体的pandas加速实战,我会在 下一期说,现在让我们来看一个小栗子:

我们首先创建了一个Series,填充了各种颜色,接着查看了每个地址对应的颜色所占内存的大小

注意这里我们使用sys.getsizeof()来获取占内存大小,但是实际上空格也是占内存的,sys.getsizeof(’’)返回的是49bytes

接下来我们想把每种颜色用占内存更少的数字来表示(机器学习种非常常见),这样可以减少占用的内存,首先让我们创建一个mapper字典,给每一种颜色指定 一个数字

接着我们把刚才的colors数组转化为int类型:

再让我们看一下占用的内存:

现在可以观察到我们的内存占用的空间几乎是之前的一半,其实,刚刚我们做的正是模拟Categorical Data的转化原理。现在让我们直接调用一下:

大家可能感觉节省的空间并不是非常大对不对? 因为目前我们这个数据根本不是真实场景,我们仅仅把数据容量增加10倍,现在再让我们看看效果:

这回内存的占用量差距明显就出来了,现在让我们用.cat来简化一下刚刚的工作:

现在让我们查看把颜色代表的数字:

我们如果不满意顺序也可以从新排序:

有关cat其他的方法,我们还是可以通过遍历dir来查看:

Categorical 数据通常不太灵活,比如我们不能直接在new_colors上新增一个新的颜色,要首先通过 .add_categories来添加

6. 利用Mapping巧妙实现映射

假设现在我们有存贮国家的一组数据,和一组用来映射国家所对应的大洲的数据:

我们可以通过下面的方法来实现简单的映射:

很简单对不对,现在让我们看一下最关键的一行代码,groups = {x: k for k, v in groups.items() for x in v},这个是我之前提到过的字典推导式:

7. 压缩pandas

如果你的pandas版本大于0.21.0,那么都可以直接把pandas用压缩形式写入,常见的类型有gzip, bz2, zip,这里我们直接用刚才鲍鱼的数据集

8. 其他

9. 总结

Last updated

Was this helpful?