本篇文章将主要介绍 Pandas 库中 DataFrame 对象的基础方法,通过学习掌握这些基础方法,我们可以高效地进行数据预处理、计算等操作,为后续的数据分析打下坚实的基础。
DataFrame 表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame 既有行索引也有列索引,它可以被视为一个共享相同索引的 Series 的字典。在 DataFrame中,数据被存储为一个以上的二维块,而不是列表、字典或其他一维数组的集合。
1、创建 DataFrame
(1)从字典创建
可以使用字典创建 DataFrame,字典的键表示列名,值是列数据(可以是列表、数组等)
import pandas as pd
data = {
'Name': ['Tom', 'Bob', 'Jack'],
'Age': [25, 30, 35],
'City': ['北京', '上海', '广州']
}
df = pd.DataFrame(data)
(2)从列表创建
可以使用列表的列表(或数组的数组)来创建 DataFrame,并指定列名
data = [ ['Tom', 25, '北京'],
['Bob', 30, '上海'],
['Jack', 35, '广州']
]
df = pd.DataFrame(data, columns=['Name', 'Age', 'City'])
(3)从 NumPy 数组创建
可以使用 NumPy 数组来创建 DataFrame ,同样可以指定列名。
import numpy as np
data = np.array([ ['Tom', 25, '北京'],
['Bob', 30, '上海'],
['Jack', 35, '广州']
])
df = pd.DataFrame(data, columns=['Name', 'Age', 'City'])
2、重建索引
reindex 是 DataFrame 对象的重要方法,该方法用于创建一个符合新索引的新对象。在 DataFrame 中,reindex可以改变行索引、列索引,也可以同时改变二者。当仅传入一个序列时,结果中的行会重建索引:
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'c', 'd'],
columns=['Tom', 'Bob', 'Jack'])
frame
# ----输出----
# Tom Bob Jack
# a 0 1 2
# c 3 4 5
# d 6 7 8
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
frame2
# ----输出----
# Tom Bob Jack
# a 0.0 1.0 2.0
# b NaN NaN NaN
# c 3.0 4.0 5.0
# d 6.0 7.0 8.0
列可以使用 columns 关键字重建索引:
frame2 = frame.reindex(columns= ['Bob', 'Mary', 'Jack'])
frame2
# ----输出----
# Bob Mary Jack
# a 1.0 NaN 2.0
# b NaN NaN NaN
# c 4.0 NaN 5.0
# d 7.0 NaN 8.0
3、轴向上删除条目
我们可以使用 drop 方法在轴向上删除一个或多个数据,如果在调用 drop 时使用标签序列会根据行标签删除值
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'c', 'd'],
columns=['Tom', 'Bob', 'Jack'])
frame
# ----输出----
# Tom Bob Jack
# a 0 1 2
# c 3 4 5
# d 6 7 8
frame.drop(['a'])
# ----输出----
# Tom Bob Jack
# c 3 4 5
# d 6 7 8
当然,我们可以通过传递 axis=1 或 axis='columns' 来从列中删除值
frame.drop('Bob', axis=1)
# ----输出----
# Tom Jack
# a 0 2
# c 3 5
# d 6 8
当然,如果我们想在原对象上操作,可以设置 inplace 参数
frame.drop('c', inplace=True)
# ----输出----
# Tom Jack
# a 0 2
# d 6 8
4、获取数据
使用单个值或序列,可以从 DataFrame 中索引出一个或多个列:
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'c', 'd'],
columns=['Tom', 'Bob', 'Jack'])
frame['Tom']
# ----输出----
# 0 0
# 1 3
# 2 6
# Name: Tom, dtype: int64
frame[['Tom', 'Bob']]
# ----输出----
# Tom Bob
# a 0 1
# c 3 4
# d 6 7
可以根据一个数值区间或者布尔值数组进行切片操作
frame[:2]
# ----输出----
# Tom Bob Jack
# a 0 1 2
# c 3 4 5
frame[frame['Bob'] > 3]
# ----输出----
# Tom Bob Jack
# c 3 4 5
# d 6 7 8
针对 DataFrame 在行上的标签索引,我们可以使用轴标签(loc)或整数标签(iloc)以 NumPy 风格的语法从DataFrame 中选出数组的行和列的子集。
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'c', 'd'],
columns=['Tom', 'Bob', 'Jack'])
frame.loc[['a', 'c'], ['Tom', 'Bob']]
# ----输出----
# Tom Bob
# a 0 1
# c 3 4
frame.iloc[[0, 1], [0, 1]]
# ----输出----
# Tom Bob
# a 0 1
# c 3 4
5、算术计算
不同 DataFrame 索引的对象之间的数值计算是根据索引对齐计算,如果存在某个索引对不相同,则返回结果的索引将是索引对的并集。如下所示,将这些对象加在一起,返回一个 DataFrame,它的索引、列是每个 DataFrame 的索引、列的并集。
由于 ‘a’列和 ‘b’行标签并不是两个 DataFrame 共有的行标签,这两行中产生了缺失值;由于 ‘Bob’列和‘Mary’列并不是两个 DataFrame 共有的列,所以产生了缺失值。
import numpy as np
frame1 = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'b', 'c'],
columns=['Tom', 'Bob', 'Jack'])
frame2 = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'b', 'c'],
columns=['Tom', 'Mary', 'Jack'])
frame1 + frame2
# ----输出----
# Bob Jack Mary Tom
# a NaN 4 NaN 0
# b NaN 10 NaN 6
# c NaN 16 NaN 12
这些缺失值会在后续的算术操作上产生影响。我们可以使用 add 实现同样的相加效果,而且有参数 fill_value 可以在相加时指定缺失值的替代值。
import numpy as np
frame1 = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'b', 'c'],
columns=['Tom', 'Bob', 'Jack'])
frame2 = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'b', 'c'],
columns=['Tom', 'Mary', 'Jack'])
frame1.add(frame2, fill_value=0)
# ----输出----
# Bob Jack Mary Tom
# a 1.0 4 1.0 0
# b 4.0 10 4.0 6
# c 7.0 16 7.0 12
当然除了,以上介绍的 add 方法外,还有以下算术方法,我们就不再分别介绍,大家根据需要使用即可。
6、函数映射
DataFrame 的 apply 方法可以实现将函数应用到一行或一列的一维数组上,如下所示:这里的函数f,可以计算 Series 最大值和最小值的差,会被 frame 中的每一列调用一次。结果是一个以 frame 的列作为索引的 Series。
import numpy as np
frame1 = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'b', 'c'],
columns=['Tom', 'Bob', 'Jack'])
f = lambda x: x.max() - x.min()
frame1.apply(f)
# ----输出----
# Tom 6
# Bob 6
# Jack 6
# dtype: int32
如果你传递 axis='columns’给 apply 函数,函数将会被每行调用一次:
f = lambda x: x.max() - x.min()
frame1.apply(f, axis='columns')
# ----输出----
# a 2
# b 2
# c 2
# dtype: int32
传递给 apply 的函数并不一定要返回一个标量值,也可以返回带有多个值的 Series:
f = lambda x: pd.Series([x.min(), x.max()], index=['min','max'])
frame1.apply(f)
# ----输出----
# Tom Bob Jack
# min 0 1 2
# max 6 7 8
如果要逐元素计算,则使用 applymap 方法,如下假设你想要根据 frame 中的每个浮点数计算一个格式化字符串:
f = lambda x: '%.2f' %x
frame1.applymap(f)
# ----输出----
# Tom Bob Jack
# a 0.00 1.00 2.00
# b 3.00 4.00 5.00
# c 6.00 7.00 8.00
7、排序
DataFrame 可以使用 sort_index 方法根据标签(列名)进行排序,该方法返回一个新的、排序好的对象:
import numpy as np
frame1 = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['b', 'a', 'c'],
columns=['Tom', 'Bob', 'Jack'])
frame1.sort_index()
# ---- 输出 ----
# Tom Bob Jack
# a 3 4 5
# b 0 1 2
# c 6 7 8
默认是根据标签进行排序,通过设置 axis=1,则会根据列名进行排序
frame1.sort_index(axis=1)
# ---- 输出 ----
# Bob Jack Tom
# b 1 2 0
# a 4 5 3
# c 7 8 6
数据默认会根据标签升序排序,但是也可以通过设置 ascending 参数按照降序排序:
frame1.sort_index(axis=1, ascending=False)
# ---- 输出 ----
# Tom Jack Bob
# b 0 2 1
# a 3 5 4
# c 6 8 7
如果要根据 DataFrame 的值进行排序,使用 sort_values 方法,可以使用一列或多列作为排序键
frame1.sort_values(by=['Bob', 'Jack'])
# ---- 输出 ----
# Tom Bob Jack
# b 0 1 2
# a 3 4 5
# c 6 7 8
8、统计计算
DataFrame 对象装配了一个常用数学、统计学方法的集合。其中大部分属于归约或汇总统计的类别,这些方法从DataFrame 的行或列中抽取一个 Series 或一系列值的单个值(如总和或平均值)。与 NumPy 数组中的类似方法相比,它们内建了处理缺失值的功能。如下我们看 DataFrame 对象的 sum 方法的一个例子,其它方法以此类推。如下所示,调用 DataFrame 的 sum 方法返回一个包含列上加和的 Series:
import pandas as pd
import numpy as np
df = pd.DataFrame([[1, np.nan], [3, 4],
[np.nan, np.nan], [7, 8]],
index=['a', 'b', 'c', 'd'],
columns=['one', 'two'])
df.sum()
# ---- 输出 ----
# one 11.0
# two 12.0
# dtype: float64
如果传入 axis='columns’或 axis=1,则会将一行上各个列的值相加:
df.sum(axis=1)
# ---- 输出 ----
# a 1.0
# b 7.0
# c 0.0
# d 15.0
# dtype: float64
从以上看到在计算时,NA 值是被自动排除的,但是我们可以通过禁用 skipna 来实现不排除 NA 值:
df.sum(axis=1, skipna=False)
# ---- 输出 ----
# a NaN
# b 7.0
# c NaN
# d 15.0
# dtype: float64
其它统计及其相关方法的使用方式类似,我们不分别举例,进行汇总完整列表如下
如果你喜欢本文,欢迎点赞,并且关注我们的微信公众号:Python技术极客,我们会持续更新分享 Python 开发编程、数据分析、数据挖掘、AI 人工智能、网络爬虫等技术文章!让大家在Python 技术领域持续精进提升,成为更好的自己!
添加作者微信(coder_0101),拉你进入行业技术交流群,进行技术交流~