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

教你学会 Pandas 不是个人目的,教你轻松玩转 Pandas 才是个人目的。我会经过一系列实例来带入 Pandas 的知识点,让你在学习 Pandas 的路上再也不枯燥。html

声明:我所写的轻松玩转 Pandas 教程都是免费的,若是对你有帮助,你能够持续关注我。python

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

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

经常使用的基本功能

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

由于大多数状况下 DataFrame 比 Series 更为经常使用,因此这里以 DataFrame 举例说明,但实际上不少经常使用功能对于 Series 也适用。函数

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 方法来查看。学习

user_info.info()
复制代码
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 方法。人工智能

user_info.head(2)
复制代码
age city sex
name
Tom 18 BeiJing male
Bob 30 ShangHai male

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

user_info.shape
复制代码
(4, 3)
复制代码
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。设计

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

描述与统计

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

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

user_info.age.max()
复制代码
40
复制代码

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

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

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

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

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

若是想要获取更多的统计方法,能够参见官方连接:Descriptive statistics

虽说常见的各类统计值都有对应的方法,若是我想要获得多个指标的话,就须要调用屡次方法,是否是显得有点麻烦呢?

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

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"] 来得到。

user_info.describe(include=["object"])
复制代码
city sex
count 4 4
unique 4 2
top BeiJing male
freq 1 3

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

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

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

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

user_info.age.idxmax()
复制代码
'James'
复制代码

离散化

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

pd.cut(user_info.age, 3)
复制代码
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 自动生成了等距的离散区间,若是本身想定义也是没问题的。

pd.cut(user_info.age, [1, 18, 30, 50])
复制代码
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 参数。

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

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

pd.qcut(user_info.age, 3)
复制代码
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 方法默认是按照索引进行正序排的。

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

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" 便可。

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 中每一个元素的顺序会影响排序优先级的

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) 方法快得多。

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

函数应用

虽然说 Pandas 为咱们提供了很是丰富的函数,有时候咱们可能须要本身定制一些函数,并将它应用到 DataFrame 或 Series。经常使用到的函数有:mapapplyapplymap

map 是 Series 中特有的方法,经过它能够对 Series 中的每一个元素实现转换。

若是我想经过年龄判断用户是否属于中年人(30岁以上为中年),经过 map 能够轻松搞定它。

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

又好比,我想要经过城市来判断是南方仍是北方,我能够这样操做。

city_map = {
    "BeiJing": "north",
    "ShangHai": "south",
    "GuangZhou": "south",
    "ShenZhen": "south"
}

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

apply 方法既支持 Series,也支持 DataFrame,在对 Series 操做时会做用到每一个值上,在对 DataFrame 操做时会做用到全部行或全部列(经过 axis 参数控制)。

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

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

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 便可。

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 便可。

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 方法。

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

若是想要转换数据类型的话,能够经过 astype 来完成。

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

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

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

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' 能够在强转失败时返回原有的数据。

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

想要学习更多关于人工智能的知识,请关注公众号:AI派

qrcode_for_gh_60cef389e81c_258.jpg

这里我将整篇文章的内容整理成了pdf,想要pdf文件的能够在公众号后台回复关键字:pandas02

更多Pandas知识见:轻松玩转Pandas

相关文章
相关标签/搜索