37

25个Pandas实用技巧

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzIzNTg3MDQyMQ%3D%3D&%3Bmid=2247487135&%3Bidx=2&%3Bsn=87b3a49d5aa21d5a21e1a72abdb63da5
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文一共为大家分享25个pandas技巧,此为上篇~

显示已安装的版本

输入下面的命令查询pandas版本:

In [7]:pd.__version__

Out[7]:'0.24.2'

如果你还想知道pandas所依赖的模块的版本,你可以使用 show_versions()函数 :

In [9]:

pd.show_versions()


INSTALLED VERSIONS

------------------

commit: None

python: 3.7.3.final.0

python-bits: 64

OS: Darwin

OS-release: 18.6.0

machine: x86_64

processor: i386

byteorder: little

LC_ALL: None

LANG: en_US.UTF-8

LOCALE: en_US.UTF-8


pandas: 0.24.2

pytest: None

pip: 19.1.1

setuptools: 41.0.1

Cython: None

numpy: 1.16.4

scipy: None

pyarrow: None

xarray: None

IPython: 7.5.0

sphinx: None

patsy: None

dateutil: 2.8.0

pytz: 2019.1

blosc: None

bottleneck: None

tables: None

numexpr: None

feather: None

matplotlib: 3.1.0

openpyxl: None

xlrd: None

xlwt: None

xlsxwriter: None

lxml.etree: None

bs4: None

html5lib: None

sqlalchemy: None

pymysql: None

psycopg2: None

jinja2: 2.10.1

s3fs: None

fastparquet: None

pandas_gbq: None

pandas_datareader: None

gcsfs: None

你可以查看到Python,pandas, Numpy, matplotlib等的版本信息。

创建示例DataFrame

假设你需要创建一个示例DataFrame。有很多种实现的途径,我最喜欢的方式是传一个字典给DataFrame constructor,其中字典中的 keys为列名,values为列的取值。

Yje67vF.png!web

现在如果你需要创建一个更大的DataFrame,上述方法则需要太多的输入。在这种情况下,你可以使用 Numpy的random.rand()函数 ,告诉它行数和列数,将它传递给DataFrame constructor:

iMRbyez.png!web

这种方式很好,但如果你还想把列名变为非数值型的,你可以强制地 将一串字符赋值给 columns参数

nYrEziQ.png!web

你可以想到,你传递的字符串的长度必须与列数相同。

更改列名

让我们来看一下刚才我们创建的示例DataFrame:

b6jI3mN.png!web

我更喜欢在选取pandas列的时候使用点(.),但是这对那么列名中含有空格的列不会生效。让我们来修复这个问题。


更改列名最灵活的方式是使用rename()函数。你可以传递一个字典,其中
keys为原列名,values为新列名 ,还可以指定axis:

In [14]:

df = df.rename({'col one':'col_one', 'col two':'col_two'}, axis='columns')

使用这个函数最好的方式是你需要更改任意数量的列名,不管是一列或者全部的列。


如果你需要一次性重新命令所有的列名,更简单的方式就是
重写DataFrame的columns属性

In [15]:

df.columns = ['col_one', 'col_two']

如果你需要做的仅仅是将空格换成下划线,那么更好的办法是使用 str.replace()方法 ,这是因为你都不需要输入所有的列名:

In [16]:

df.columns = df.columns.str.replace(' ', '_')

上述三个函数的结果都一样,可以更改列名使得列名中不含有空格:

MjUbeef.png!web

最后,如果你需要在列名中添加前缀或者后缀,你可以使用 add_prefix()函数

AvueMrf.png!web

或者使用 add_suffix()函数

j2mIn2e.png!web

行序反转

让我们来看一下drinks这个DataFame:

In [20]:

drinks.head()


Out[20]:

country beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol continent 0 Afghanistan 0 0 0 0.0 Asia 1 Albania 89 132 54 4.9 Europe 2 Algeria 25 0 14 0.7 Africa 3 Andorra 245 138 312 12.4 Europe 4 Angola 217 57 45 5.9 Africa

该数据集描述了每个国家的平均酒消费量。如果你想要将行序反转呢?

最直接的办法是使用 loc函数并传递::-1 ,跟Python中列表反转时使用的切片符号一致:

In [21]:

drinks.loc[::-1].head()


Out[21]:

country beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol continent 192 Zimbabwe 64 18 4 4.7 Africa 191 Zambia 32 19 4 2.5 Africa 190 Yemen 6 0 0 0.1 Asia 189 Vietnam 111 2 1 2.0 Asia 188 Venezuela 333 100 3 7.7 South America


如果你还想重置索引使得它从0开始呢?


你可以使用
reset_index()函数 ,告诉他去 掉完全抛弃之前的索引

In [22]:

drinks.loc[::-1].reset_index(drop=True).head()


Out[22]:

country beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol continent 0 Zimbabwe 64 18 4 4.7 Africa 1 Zambia 32 19 4 2.5 Africa 2 Yemen 6 0 0 0.1 Asia 3 Vietnam 111 2 1 2.0 Asia 4 Venezuela 333 100 3 7.7 South America

你可以看到,行序已经反转,索引也被重置为默认的整数序号。

列序反转

跟之前的技巧一样,你也可以使用loc函数将列从左至右反转:

In [23]:

drinks.loc[:, ::-1].head()


Out[23]:

continent total_litres_of_pure_alcohol wine_servings spirit_servings beer_servings country 0 Asia 0.0 0 0 0 Afghanistan 1 Europe 4.9 54 132 89 Albania 2 Africa 0.7 14 0 25 Algeria 3 Europe 12.4 312 138 245 Andorra 4 Africa 5.9 45 57 217 Angola

逗号之前的冒号表示选择所有行,逗号之后的::-1表示反转所有的列,这就是为什么country这一列现在在最右边。

通过数据类型选择列

这里有drinks这个DataFrame的数据类型:

In [24]:

drinks.dtypes


Out[24]:

country object

beer_servings int64

spirit_servings int64

wine_servings int64

total_litres_of_pure_alcohol float64

continent object

dtype: object

假设你仅仅需要 选取数值型的列 ,那么你可以使用 select_dtypes()函数

In [25]:

drinks.select_dtypes(include='number').head()


Out[25]:

beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol 0 0 0 0 0.0 1 89 132 54 4.9 2 25 0 14 0.7 3 245 138 312 12.4 4 217 57 45 5.9

这包含了int和float型的列。


你也可以使用这个函数来选取数据类型为object的列:

IF3Qjmr.png!web

你还可以选取多种数据类型,只需要传递一个列表即可:

6BBbqur.png!web

你还可以用来排除特定的数据类型:

yArqMr6.png!web

将字符型转换为数值型

让我们来创建另一个示例DataFrame:

fueQnqv.png!web

这些数字实际上储存为 字符型 ,导致其数据类型为object:

yqMBnem.png!web

为了对这些列进行数学运算,我们需要 将数据类型转换成数值型 。你可以对前两列使用 astype()函数

AF3Ez2A.png!web

但是,如果你对第三列也使用这个函数,将会引起错误,这是因为这一列包含了破折号(用来表示0)但是pandas并不知道如何处理它。

你可以对第三列使用to_numeric()函数,告诉其将任何无效数据转换为NaN:

3aUbArQ.png!web

如果你知道NaN值代表0,那么你可以fillna()函数将他们替换成0:

IFzIfaM.png!web

最后,你可以通过apply()函数一次性对整个DataFrame使用这个函数:

zy26RvN.png!web

仅需一行代码就完成了我们的目标,因为现在所有的数据类型都转换成float:

jiEraie.png!web

减小DataFrame空间大小

pandas DataFrame被设计成可以适应内存,所以有些时候你可以减小DataFrame的空间大小,让它在你的系统上更好地运行起来。


这是drinks这个DataFrame所占用的空间大小:

RjmmUv3.png!web

可以看到它使用了30.4KB。


如果你对你的DataFrame有操作方面的问题,或者你不能将它读进内存,那么在读取文件的
过程中有两个步骤可以使用来减小DataFrame的空间大小。

第一个步骤是只读取那些你实际上需要用到的列,可以调用usecols参数:

jINBBfm.png!web

通过仅读取用到的两列,我们将DataFrame的空间大小缩小至13.6KB。


第二步是将所有实际上为类别变量的object列转换成类别变量,可以调用dtypes参数:

UnMZFnY.png!web

通过将continent列读取为category数据类型,我们进一步地把DataFrame的空间大小缩小至2.3KB。


值得注意的是,如果跟行数相比,category数据类型的列数相对较小,那么catefory数据类型可以减小内存占用。

按行从多个文件中构建DataFrame

假设你的数据集分化为多个文件,但是你需要将这些数据集读到一个DataFrame中。


举例来说,我有一些关于股票的小数聚集,每个数据集为单天的CSV文件。 这是第一天的:

Jv6FneZ.png!web

这是第二天的:

jQnY3qR.png!web

这是第三天的:

VnUbYn6.png!web

你可以将每个CSV文件读取成DataFrame,将它们结合起来,然后再删除原来的DataFrame,但是这样会多占用内存且需要许多代码


更好的方式为使用内置的glob模块。你可以给glob()函数传递某种模式,包括未知字符,这样它会返回符合该某事的文件列表。在这种方式下,glob会查找所有以stocks开头的CSV文件:

eaAbYr2.png!web

glob会返回任意排序的文件名,这就是我们为什么要用Python内置的sorted()函数来对列表进行排序。


我们以生成器表达式用read_csv()函数来读取每个文件,并将结果传递给concat()函数,这会将单个的DataFrame按行来组合:

uIjQjiy.png!web

不幸的是,索引值存在重复。为了避免这种情况,我们需要告诉concat()函数来忽略索引,使用默认的整数索引:

iEn6RjJ.png!web

按列从多个文件中构建DataFrame

上一个技巧对于数据集中每个文件包含行记录很有用。但是如果数据集中的每个文件包含的列信息呢?


这里有一个例子,dinks数据集被划分成两个CSV文件,每个文件包含三列:

iyqyEfE.png!web

同上一个技巧一样,我们以使用glob()函数开始。这一次,我们需要告诉concat()函数按列来组合:

iMreUbZ.jpg!web

现在我们的DataFrame已经有六列了。

End.

译者:山阴少年

来源:博客园

原文链接:https://nbviewer.jupyter.org/github/justmarkham/pandas-videos/blob/master/top_25_pandas_tricks.ipynb

本文为转载,如有侵权请联系后台删除

好文章,我 在看 :heart:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK