前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pandas基本功能详解 | 轻松玩转Pandas(2)

Pandas基本功能详解 | 轻松玩转Pandas(2)

作者头像
abs_zero
发布2018-07-25 09:54:19
1.9K0
发布2018-07-25 09:54:19
举报
文章被收录于专栏:AI派

教你学会 Pandas 不是我的目的,教你轻松玩转 Pandas 才是我的目的。我会通过一系列实例来带入 Pandas 的知识点,让你在学习 Pandas 的路上不再枯燥。 声明:我所写的轻松玩转 Pandas 教程都是免费的,如果对你有帮助,你可以持续关注我。

Pandas数据结构详解 | 轻松玩转Pandas(1) 介绍了 Pandas 中常用的两种数据结构 Series 以及 DataFrame,这里来看下这些数据结构都有哪些常用的功能。

代码语言:javascript
复制
# 导入相关库
import numpy as np
import pandas as pd

常用的基本功能

当我们构建好了 Series 和 DataFrame 之后,我们会经常使用哪些功能呢?来跟我看看吧。引用上一章节中的场景,我们有一些用户的的信息,并将它们存储到了 DataFrame 中。

因为大多数情况下 DataFrame 比 Series 更为常用,所以这里以 DataFrame 举例说明,但实际上很多常用功能对于 Series 也适用。

代码语言:javascript
复制
index = pd.Index(data=["Tom", "Bob", "Mary", "James"], name="name")

data = {
    "age": [18, 30, 25, 40],
    "city": ["BeiJing", "ShangHai", "GuangZhou", "ShenZhen"],
    "sex": ["male", "male", "female", "male"]
}

user_info = pd.DataFrame(data=data, index=index)
user_info

age

city

sex

name

Tom

18

BeiJing

male

Bob

30

ShangHai

male

Mary

25

GuangZhou

female

James

40

ShenZhen

male

一般拿到数据,我们第一步需要做的是了解下数据的整体情况,可以使用 info 方法来查看。

代码语言:javascript
复制
user_info.info()
代码语言:javascript
复制
Index: 4 entries, Tom to James
Data columns (total 3 columns):
age     4 non-null int64
city    4 non-null object
sex     4 non-null object
dtypes: int64(1), object(2)
memory usage: 128.0+ bytes

如果我们的数据量非常大,我想看看数据长啥样,我当然不希望查看所有的数据了,这时候我们可以采用只看头部的 n 条或者尾部的 n 条。查看头部的 n 条数据可以使用 head 方法,查看尾部的 n 条数据可以使用 tail 方法。

代码语言:javascript
复制
user_info.head(2)

age

city

sex

name

Tom

18

BeiJing

male

Bob

30

ShangHai

male

此外,Pandas 中的数据结构都有 ndarray 中的常用方法和属性,如通过 .shape 获取数据的形状,通过 .T 获取数据的转置。

代码语言:javascript
复制
user_info.shape
代码语言:javascript
复制
(4, 3)
代码语言:javascript
复制
user_info.T

name

Tom

Bob

Mary

James

age

18

30

25

40

city

BeiJing

ShangHai

GuangZhou

ShenZhen

sex

male

male

female

male

如果我们想要通过 DataFrame 来获取它包含的原有数据,可以通过 .values 来获取,获取后的数据类型其实是一个 ndarray。

代码语言:javascript
复制
user_info.values
代码语言:javascript
复制
array([[18, 'BeiJing', 'male'],
       [30, 'ShangHai', 'male'],
       [25, 'GuangZhou', 'female'],
       [40, 'ShenZhen', 'male']], dtype=object)

描述与统计

有时候我们获取到数据之后,想要查看下数据的简单统计指标(最大值、最小值、平均值、中位数等),比如想要查看年龄的最大值,如何实现呢?

直接对 age 这一列调用 max方法即可。

代码语言:javascript
复制
user_info.age.max()
代码语言:javascript
复制
40

类似的,通过调用 minmeanquantilesum 方法可以实现最小值、平均值、中位数以及求和。可以看到,对一个 Series 调用 这几个方法之后,返回的都只是一个聚合结果。

来介绍个有意思的方法:cumsum,看名字就发现它和 sum 方法有关系,事实上确实如此,cumsum 也是用来求和的,不过它是用来累加求和的,也就是说它得到的结果与原始的 SeriesDataFrame 大小相同。

代码语言:javascript
复制
user_info.age.cumsum()
代码语言:javascript
复制
name
Tom       18
Bob       48
Mary      73
James    113
Name: age, dtype: int64

可以看到,cummax 最后的结果就是将上一次求和的结果与原始当前值求和作为当前值。这话听起来有点绕。举个例子,上面的 73 = 48 + 25cumsum 也可以用来操作字符串类型的对象。

代码语言:javascript
复制
user_info.sex.cumsum()
代码语言:javascript
复制
name
Tom                    male
Bob                malemale
Mary         malemalefemale
James    malemalefemalemale
Name: sex, dtype: object

如果想要获取更多的统计方法,可以参见官方链接:Descriptive statistics

虽然说常见的各种统计值都有对应的方法,如果我想要得到多个指标的话,就需要调用多次方法,是不是显得有点麻烦呢?

Pandas 设计者自然也考虑到了这个问题,想要一次性获取多个统计指标,只需调用 describe 方法即可

代码语言:javascript
复制
user_info.describe()

age

count

4.000000

mean

28.250000

std

9.251126

min

18.000000

25%

23.250000

50%

27.500000

75%

32.500000

max

40.000000

可以看到,直接调用 describe 方法后,会显示出数字类型的列的一些统计指标,如 总数、平均数、标准差、最小值、最大值、25%/50%/75% 分位数。如果想要查看非数字类型的列的统计指标,可以设置 include=["object"] 来获得。

代码语言:javascript
复制
user_info.describe(include=["object"])

city

sex

count

4

4

unique

4

2

top

BeiJing

male

freq

1

3

上面的结果展示了非数字类型的列的一些统计指标:总数,去重后的个数、最常见的值、最常见的值的频数。

此外,如果我想要统计下某列中每个值出现的次数,如何快速实现呢?调用 value_counts 方法快速获取 Series 中每个值出现的次数。

代码语言:javascript
复制
user_info.sex.value_counts()
代码语言:javascript
复制
male      3
female    1
Name: sex, dtype: int64

如果想要获取某列最大值或最小值对应的索引,可以使用 idxmaxidxmin 方法完成。

代码语言:javascript
复制
user_info.age.idxmax()
代码语言:javascript
复制
'James'

离散化

有时候,我们会碰到这样的需求,想要将年龄进行离散化(分桶),直白来说就是将年龄分成几个区间,这里我们想要将年龄分成 3 个区间段。就可以使用 Pandas 的 cut 方法来完成。

代码语言:javascript
复制
pd.cut(user_info.age, 3)
代码语言:javascript
复制
name
Tom      (17.978, 25.333]
Bob      (25.333, 32.667]
Mary     (17.978, 25.333]
James      (32.667, 40.0]
Name: age, dtype: category
Categories (3, interval[float64]): [(17.978, 25.333] < (25.333, 32.667] < (32.667, 40.0]]

可以看到, cut 自动生成了等距的离散区间,如果自己想定义也是没问题的。

代码语言:javascript
复制
pd.cut(user_info.age, [1, 18, 30, 50])
代码语言:javascript
复制
name
Tom       (1, 18]
Bob      (18, 30]
Mary     (18, 30]
James    (30, 50]
Name: age, dtype: category
Categories (3, interval[int64]): [(1, 18] < (18, 30] < (30, 50]]

有时候离散化之后,想要给每个区间起个名字,可以指定 labels 参数。

代码语言:javascript
复制
pd.cut(user_info.age, [1, 18, 30, 50], labels=["childhood", "youth", "middle"])
代码语言:javascript
复制
name
Tom      childhood
Bob          youth
Mary         youth
James       middle
Name: age, dtype: category
Categories (3, object): [childhood < youth < middle]

除了可以使用 cut 进行离散化之外,qcut 也可以实现离散化。cut 是根据每个值的大小来进行离散化的,qcut 是根据每个值出现的次数来进行离散化的。

代码语言:javascript
复制
pd.qcut(user_info.age, 3)
代码语言:javascript
复制
name
Tom      (17.999, 25.0]
Bob        (25.0, 30.0]
Mary     (17.999, 25.0]
James      (30.0, 40.0]
Name: age, dtype: category
Categories (3, interval[float64]): [(17.999, 25.0] < (25.0, 30.0] < (30.0, 40.0]]

排序功能

在进行数据分析时,少不了进行数据排序。Pandas 支持两种排序方式:按轴(索引或列)排序和按实际值排序。

先来看下按索引排序:sort_index 方法默认是按照索引进行正序排的。

代码语言:javascript
复制
user_info.sort_index()

age

city

sex

name

Bob

30

ShangHai

male

James

40

ShenZhen

male

Mary

25

GuangZhou

female

Tom

18

BeiJing

male

如果想要按照列进行倒序排,可以设置参数 axis=1ascending=False

代码语言:javascript
复制
user_info.sort_index(axis=1, ascending=False)

sex

city

age

name

Tom

male

BeiJing

18

Bob

male

ShangHai

30

Mary

female

GuangZhou

25

James

male

ShenZhen

40

如果想要实现按照实际值来排序,例如想要按照年龄排序,如何实现呢?

使用 sort_values 方法,设置参数 by="age" 即可。

代码语言:javascript
复制
user_info.sort_values(by="age")

age

city

sex

name

Tom

18

BeiJing

male

Mary

25

GuangZhou

female

Bob

30

ShangHai

male

James

40

ShenZhen

male

有时候我们可能需要按照多个值来排序,例如:按照年龄和城市来一起排序,可以设置参数 by 为一个 list 即可。

注意:list 中每个元素的顺序会影响排序优先级的

代码语言:javascript
复制
user_info.sort_values(by=["age", "city"])

age

city

sex

name

Tom

18

BeiJing

male

Mary

25

GuangZhou

female

Bob

30

ShangHai

male

James

40

ShenZhen

male

一般在排序后,我们可能需要获取最大的n个值或最小值的n个值,我们可以使用 nlargestnsmallest 方法来完成,这比先进行排序,再使用 head(n) 方法快得多。

代码语言:javascript
复制
user_info.age.nlargest(2)
代码语言:javascript
复制
name
James    40
Bob      30
Name: age, dtype: int64

函数应用

虽说 Pandas 为我们提供了非常丰富的函数,有时候我们可能需要自己定制一些函数,并将它应用到 DataFrame 或 Series。常用到的函数有:mapapplyapplymap

map 是 Series 中特有的方法,通过它可以对 Series 中的每个元素实现转换。

如果我想通过年龄判断用户是否属于中年人(30岁以上为中年),通过 map 可以轻松搞定它。

代码语言:javascript
复制
# 接收一个 lambda 函数
user_info.age.map(lambda x: "yes" if x >= 30 else "no")
代码语言:javascript
复制
name
Tom       no
Bob      yes
Mary      no
James    yes
Name: age, dtype: object

又比如,我想要通过城市来判断是南方还是北方,我可以这样操作。

代码语言:javascript
复制
city_map = {
    "BeiJing": "north",
    "ShangHai": "south",
    "GuangZhou": "south",
    "ShenZhen": "south"
}

# 传入一个 map
user_info.city.map(city_map)
代码语言:javascript
复制
name
Tom      north
Bob      south
Mary     south
James    south
Name: city, dtype: object

apply 方法既支持 Series,也支持 DataFrame,在对 Series 操作时会作用到每个值上,在对 DataFrame 操作时会作用到所有行或所有列(通过 axis 参数控制)。

代码语言:javascript
复制
# 对 Series 来说,apply 方法 与 map 方法区别不大。
user_info.age.apply(lambda x: "yes" if x >= 30 else "no")
代码语言:javascript
复制
name
Tom       no
Bob      yes
Mary      no
James    yes
Name: age, dtype: object
代码语言:javascript
复制
# 对 DataFrame 来说,apply 方法的作用对象是一行或一列数据(一个Series)
user_info.apply(lambda x: x.max(), axis=0)
代码语言:javascript
复制
age           40
city    ShenZhen
sex         male
dtype: object

applymap 方法针对于 DataFrame,它作用于 DataFrame 中的每个元素,它对 DataFrame 的效果类似于 apply 对 Series 的效果。

代码语言:javascript
复制
user_info.applymap(lambda x: str(x).lower())

age

city

sex

name

Tom

18

beijing

male

Bob

30

shanghai

male

Mary

25

guangzhou

female

James

40

shenzhen

male

修改列/索引名称

在使用 DataFrame 的过程中,经常会遇到修改列名,索引名等情况。使用 rename 轻松可以实现。

修改列名只需要设置参数 columns 即可。

代码语言:javascript
复制
user_info.rename(columns={"age": "Age", "city": "City", "sex": "Sex"})

Age

City

Sex

name

Tom

18

BeiJing

male

Bob

30

ShangHai

male

Mary

25

GuangZhou

female

James

40

ShenZhen

male

类似的,修改索引名只需要设置参数 index 即可。

代码语言:javascript
复制
user_info.rename(index={"Tom": "tom", "Bob": "bob"})

age

city

sex

name

tom

18

BeiJing

male

bob

30

ShangHai

male

Mary

25

GuangZhou

female

James

40

ShenZhen

male

类型操作

如果想要获取每种类型的列数的话,可以使用 get_dtype_counts 方法。

代码语言:javascript
复制
user_info.get_dtype_counts()
代码语言:javascript
复制
int64     1
object    2
dtype: int64

如果想要转换数据类型的话,可以通过 astype 来完成。

代码语言:javascript
复制
user_info["age"].astype(float)
代码语言:javascript
复制
name
Tom      18.0
Bob      30.0
Mary     25.0
James    40.0
Name: age, dtype: float64

有时候会涉及到将 object 类型转为其他类型,常见的有转为数字、日期、时间差,Pandas 中分别对应 to_numericto_datetimeto_timedelta 方法。

这里给这些用户都添加一些关于身高的信息。

代码语言:javascript
复制
user_info["height"] = ["178", "168", "178", "180cm"]
user_info

age

city

sex

height

name

Tom

18

BeiJing

male

178

Bob

30

ShangHai

male

168

Mary

25

GuangZhou

female

178

James

40

ShenZhen

male

180cm

现在将身高这一列转为数字,很明显,180cm 并非数字,为了强制转换,我们可以传入 errors 参数,这个参数的作用是当强转失败时的处理方式。

默认情况下,errors='raise',这意味着强转失败后直接抛出异常,设置 errors='coerce' 可以在强转失败时将有问题的元素赋值为 pd.NaT(对于datetime和timedelta)或 np.nan(数字)。设置 errors='ignore' 可以在强转失败时返回原有的数据。

代码语言:javascript
复制
pd.to_numeric(user_info.height, errors="coerce")
代码语言:javascript
复制
name
Tom      178.0
Bob      168.0
Mary     178.0
James      NaN
Name: height, dtype: float64
代码语言:javascript
复制
pd.to_numeric(user_info.height, errors="ignore")
代码语言:javascript
复制
name
Tom        178
Bob        168
Mary       178
James    180cm
Name: height, dtype: object

往期精彩回顾

BAT机器学习/深度学习面试300题

Numpy 精品系列教程汇总(你值得拥有)

谷歌机器学习43条黄金法则(手册版+PDF)

吴恩达|机器学习秘籍(Machine Learning Yearning)

作者:无邪 个人博客:脑洞大开(www.naodongopen.com) 研究领域:机器学习/推荐系统

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI派 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 常用的基本功能
  • 描述与统计
  • 离散化
  • 排序功能
  • 函数应用
  • 修改列/索引名称
  • 类型操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档