数据分析必备:掌握 Pandas DataFrame 核心操作

176 阅读7分钟

本篇文章将主要介绍 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),拉你进入行业技术交流群,进行技术交流~