Pandas(一)

Pandas 学习系列(一)

Series

带索引和名称的一维数组。在Series中数据类型可以是整数、浮点数、字符串、Python对象等。

1
2
3
# 导入相关库
import numpy as np
import pandas as pd

首先,我们存储一组年龄数据:

1
2
3
ages = [18, 30, 25, 40]
pd_ages = pd.Series(data=ages)
pd_ages
0    18
1    30
2    25
3    40
dtype: int64

但如果只存储这一组数据的话好像也没什么用,我们可以试着把用户的名字加进去:

1
2
pd_ages.index = ['Tom', 'Bob', 'Mary', 'James']
pd_ages
Tom      18
Bob      30
Mary     25
James    40
dtype: int64

现在我们已经把每个人的名字和年龄对应出来了,但是不知道的人怎么能知道“Tom”、“Bob”这些是人名呢,所以我们还可以为这个索引加上名称:

1
2
pd_ages.index.name = 'username'
pd_ages
username
Tom      18
Bob      30
Mary     25
James    40
dtype: int64

对于这段数据我们还可以像起个表名一样,给Series起个名字:

1
2
pd_ages.name = 'user_age_info'
pd_ages
username
Tom      18
Bob      30
Mary     25
James    40
Name: user_age_info, dtype: int64

上面把这些步骤都一步步分开了,我们还可以快速实现:

1
2
3
4
5
# 构建索引
name = pd.Index(['Tom', 'Bob', 'Mary', 'James'], name='username')
# 构建Series
pd_age = pd.Series(data=[18, 30, 25, 40], index=name, name='user_age_info')
pd_age
username
Tom      18
Bob      30
Mary     25
James    40
Name: user_age_info, dtype: int64

上面构建Series的时候没有指定数据的类型,是由Pandas自动判断的,我们当然可以自己指定数据的类型:

1
2
3
# 指定类型为浮点型
pd_age = pd.Series(data=[18, 30, 25, 40], index=name, name="user_age_info", dtype=float)
pd_age
username
Tom      18.0
Bob      30.0
Mary     25.0
James    40.0
Name: user_age_info, dtype: float64

探索Series

由于有索引的存在,Series和dict很像,所以也具有dict的一些类似操作:

1
2
# 获取 Tom 的年龄
pd_age['Tom']
18.0
1
pd_age.get('Tom')
18.0

除了和dict很像,Series也有ndarray的类似操作:

1
2
# 获取第一个元素
pd_age[0]
18.0
1
2
# 获取前三个元素
pd_age[:3]
username
Tom     18.0
Bob     30.0
Mary    25.0
Name: user_age_info, dtype: float64
1
2
# 获取年龄大于 30 的元素
pd_age[pd_age > 30]
username
James    40.0
Name: user_age_info, dtype: float64
1
2
# 获取第 4 个元素和第 1 个元素
pd_age[[3, 0]]
username
James    40.0
Tom      18.0
Name: user_age_info, dtype: float64

Series向量化操作

Series和ndarray一样,也是支持向量化操作,同时也可以传递给大多数期望ndarray的Numpy方法:

1
pd_age + 1
username
Tom      19.0
Bob      31.0
Mary     26.0
James    41.0
Name: user_age_info, dtype: float64
1
np.exp(pd_age)
username
Tom      6.565997e+07
Bob      1.068647e+13
Mary     7.200490e+10
James    2.353853e+17
Name: user_age_info, dtype: float64

DataFrame

DataFrame 可以理解为二维的 Series。每一列都可以拥有自己的名字,数据类型也可以不一样。

接着上面的例子,这次我们不止要存储用户的年龄,还要存储城市信息,那我们该如何构建 Dataframe 呢?

我们可以把每个用户的数据存在一个个列表中传过去:

1
2
3
4
5
6
7
Tom = [18, 'Shanghai']
Bob = [30, 'Beijing']
Mary = [25, 'Guangzhou']
James = [40, 'Shenzhen']

user_info = pd.DataFrame(data=[Tom, Bob, Mary, James])
user_info
0 1
0 18 Shanghai
1 30 Beijing
2 25 Guangzhou
3 40 Shenzhen

同样,这样一张光秃秃的表格,除了数据我们一无所知。为了以后查阅方便我们得添加点额外信息:

1
2
3
4
5
6
columns = ['age', 'city']
index = ['Tom', 'Bob', 'Mary', 'James']
user_info.columns = columns
user_info.index = index

user_info
age city
Tom 18 Shanghai
Bob 30 Beijing
Mary 25 Guangzhou
James 40 Shenzhen

除此之外,我们也可直接传入 dict 数据,dict 的 key 即为该数据的 column:

1
2
3
4
5
6
7
user_data = {
'age': [18, 30, 25, 40],
'city': ['Shanghai', 'Beijing', 'Guangzhou', 'Shenzhen']
}
user_info = pd.DataFrame(data=user_data, index=index)

user_info
age city
Tom 18 Shanghai
Bob 30 Beijing
Mary 25 Guangzhou
James 40 Shenzhen

访问数据

访问行

从打印出来的 DataFrame 可见,每一行就表示一个用户的数据,那我们需要取某一个用户的数据时该怎么做呢?

直接通过索引访问:

1
2
# 通过索引名称访问
user_info.loc['Tom']
age           18
city    Shanghai
Name: Tom, dtype: object
1
2
# 通过索引角标访问
user_info.iloc[0]
age           18
city    Shanghai
Name: Tom, dtype: object
1
2
# 还支持切片操作
user_info.iloc[1:3]
age city
Bob 30 Beijing
Mary 25 Guangzhou
1
2
# 同样还支持索引名称操作!
user_info.loc['Tom': 'Mary']
age city
Tom 18 Shanghai
Bob 30 Beijing
Mary 25 Guangzhou

DataFrame 的索引操作还可以直接这么做:

1
user_info['Tom': 'Bob']
age city
Tom 18 Shanghai
Bob 30 Beijing
1
user_info[1: 2]
age city
Bob 30 Beijing

访问列

如果我想获取所有人的年龄信息,即访问数据的列数据,有两种办法:

一、使用 .attr 操作:

1
user_info.age
Tom      18
Bob      30
Mary     25
James    40
Name: age, dtype: int64

二、使用 ['attr'] 操作:

1
user_info['age']
Tom      18
Bob      30
Mary     25
James    40
Name: age, dtype: int64

那要是相同时获取多个列的数据呢?直接传入列的列表即可:

1
user_info[['age', 'city']]
age city
Tom 18 Shanghai
Bob 30 Beijing
Mary 25 Guangzhou
James 40 Shenzhen

增加/删除列

一个 DataFrame 构建完成之后,如果我们还想增加/删除某一列该怎么办呢?

还记得我们可以直接传递一个 dict 到 DataFrame 吗,同样,我们可以像操作字典一样直接加 column:

1
2
3
user_info['gender'] = 'male'

user_info
age city gender
Tom 18 Shanghai male
Bob 30 Beijing male
Mary 25 Guangzhou male
James 40 Shenzhen male

想删除某一列,同样如此简单:

1
2
3
user_info.pop('gender')

user_info
age city
Tom 18 Shanghai
Bob 30 Beijing
Mary 25 Guangzhou
James 40 Shenzhen

当然,给 DataFrame 增加列时,可以传入列表(不过要注意,如果列表元素长度不匹配会报错):

1
2
3
user_info['gender'] = ['male', 'male', 'female', 'male']

user_info
age city gender
Tom 18 Shanghai male
Bob 30 Beijing male
Mary 25 Guangzhou female
James 40 Shenzhen male

上面都会在原来的 DataFrame 上做出修改,如果想保留原来的 DataFrame 不变,所有的修改产生出新的 DataFrame 的话,可以使用 assign 方法:

1
2
3
new_user_info = user_info.assign(next_year_age=user_info['age'] + 1)

user_info
age city gender
Tom 18 Shanghai male
Bob 30 Beijing male
Mary 25 Guangzhou female
James 40 Shenzhen male
1
new_user_info
age city gender next_year_age
Tom 18 Shanghai male 19
Bob 30 Beijing male 31
Mary 25 Guangzhou female 26
James 40 Shenzhen male 41