在上一篇文章中,我们了解了如何使用 pandas 的函数来从多种数据源:csv、excel 和 html 网页。其中不管是哪一种数据读取的方式,最终返回的都是一个 DataFrame 对象。
对于 DataFrame 对象,我们只是简单将其打印出来,这一篇我们来学习围绕 DataFrame 的基本操作(添加行、列,删除行、列,排序等),除了 DataFrame,也会介绍另外一个重要的 pandas 数据结构: Series。
首先介绍 pandas 中的三个最常见的概念:index、Series 和 DataFrame。
1、数据的“目录”: index
index 也叫索引,索引是计算机科学中非常常见的概念,可能听起来会有点陌生,但其实应该很早之前就打过交道了。比如看一本书,书的目录就是书本内容的索引。所以通俗意义上,索引可以理解为就是存储了如何访问某块数据方式的数据。拿目录的例子来说,目录本身也是数据,但这个数据的内容是如何访问另一块数据(书的正文)。
在我们之前的文章中,我们也或多或少和索引打过交道。比如我们通过列表的下标访问列表的某个元素,比如 a[5] ,这个 5 也叫列表的索引。字典的场景中,我们通过 key 来访问字典中的某个元素,比如: student["name"],这个 "name" 的字符串,也属于字典的索引。
2、一维数据序列:Series
Series 本身是一种数据类型,很像我们之前打过交道的列表,是存储多个数据元素的容器。事实上,我们也可以直接使用一个列表来创建一个 Series。但与列表不同的是,Series 一般由两部分组成:index 和 values。
- values 容易理解,顾名思义就是存储了 Series 里面的所有元素的值,所以 values 部分可以认为就是和列表是等价的。
- index 部分代表代表 Series 的索引。根据上面对于索引的定义,index 部分的数据就是为了能方便地定位到 values 里面的数据。
Series 有一个单独的索引项,这就使得它既支持类似列表一样的数字索引,也支持类似字典一样的用字符串或者其他 Python 对象来做索引。对于 Series,可以简单理解成是一个列表和字典的集合体。
接下来用几个实例来简单介绍一下 Series 的概念。
(1)直接从列表创建 Series
import pandas as pd
# 通过列表创建 Series
ser1 = pd.Series([1,3,5,7])
# 通过 notebook 打印 ser1
ser1
输出显示如下:
0 1
1 3
2 5
3 7
dtype: int64
输出有两列,第一列是 index,第二列是 values, values 就是我们传入的列表,而 index 则是对应的序号。当我们只使用列表来创建 Series 对象时,会生成默认的索引。即类似列表那样,每一个元素的位置作为索引。Series 对象也具备 index 和 values 属性,这样我们可以单独访问这两个部分。
print("values: ", ser1.values)
print("index: ", ser1.index)
从以下输出结果可以看到,values 其实就是我们传入的列表,而 index 则是一个 RangeIndex 的对象。
values: [1 3 5 7]
index: RangeIndex(start=0, stop=4, step=1)
对于这个 Series 对象,我们可以通过 index 的值来获得对应 values 里面的值。比如 index 等于 1 对应的是 values 里面的 3。在代码中想要获得 1 对应的值就可以这样:
ser1[1]
输出就是:
3
(2)创建 Series,并指定索引
在上面的例子中,我们直接从一个列表创建了 Series,Series 为其分配了默认的 index,即元素在列表中的位置作为其对应的 index,比如 5 是列表 1,3,5,7 中的第三个数字,则它的 index 就是 2(从 0 开始数起)。
除了这种方式,Series 还支持我们在创建的时候指定对应的索引。
# 使用列表创建 Series,并指定其索引为另一个列表
ser2 = pd.Series([1,3,5,7], index=["a", "b", "c", "d"])
# 使用 notebook 打印 ser2
ser2
输出为:
a 1
b 3
c 5
d 7
dtype: int64
可以看到,我们指定了一个由 4 个字符串的列表作为数字列表的索引。两个列表的元素是一一对应的关系,比如字符串 "a" 就是数字 1 的索引,字符串 "b" 就是数字 3 的索引。可以验证一下:
print(ser2["d"])
输出:
7
总结一下, Series 可以看成是高级的列表或者字典,当不指定 index 的时候,Series 会生成默认的位置索引,这样的 Series 就像是一个列表。而当我们指定了 index 之后,则可以通过 index 列表中的元素来访问对应的 values 中的元素,就像字典的 key-value 结构一样。
整体来说,Series 通过将 index 和 values 分别存储的机制,实现了列表和字典的结合。
3、二维数据表:DataFrame
看完了 Series,现在我们来看上一篇经常出现的 DataFrame。在上一篇文章中,我们都是从各种文件中加载数据,之后直接存储为 DataFrame。这个部分我们来一步步地揭开 DataFrame 的神秘面纱。
(1)DataFrame 的组成
DataFrame 是一个由行和列组成的二维表格。DataFrame 其实就是由 Series 组成的,DataFrame 的某一行,或者某一列都是一个 Series。
下面我们来实验一下,将上一篇文章生成的tv_rating.csv文件加载到进来读取一下:
# 加载电视剧评分数据
df_rating = pd.read_csv("tv_rating.csv")
# 输出评分的 DataFrame
df_rating
输出为:
在上述表格中,无论是列(比如标题、评分)或者行(比如第二行、第三行)都是 Series。其中 title、rating、stars 则是列的索引。而 0、1、2...9719 是行的索引。
# 获取 rating 这一列,存储在ser_rating 变量中
ser_rating = df_rating["rating"]
# 输出 ser_rating 这个 Series
print(ser_rating)
# 分割一下,方便查看
print("------------分割一下------------")
# 查看数据的类型
print(type(ser_rating))
0 3.7分
1 4.0分
2 4.6分
3 3.4分
4 4.4分
...
3595 4.0分
3596 4.0分
3597 1.0分
3598 2.0分
9719 4.6分
Name: rating, Length: 9719, dtype: object
------------分割一下------------
<class 'pandas.core.series.Series'>
可以看到,分数的这一列被打印出来,格式和上面的 Series 是一样的,左边是 index,右边是 values。之后我们通过 type 函数获得了 ser_rating 变量的类型,确实也是 Series。
除了输出某一列,我们还可以用行索引,来单独输出某一行。比如我们输出第二行:欢喜一家人之加油宝贝,对应的索引是 1。我们可以用如下的代码获取这一行。
# DataFrame 通过 loc 函数可以查看行索引对应的值
# 取出行索引为 1 的行,存储在 ser_1 变量中
ser_1 = df_rating.loc[1]
# 打印 ser1 这个 Series
print(df_rating.loc[1])
# 分割一下,方便查看
print("------------分割一下------------")
# 查看数据的类型
print(type(df_rating.loc[1]))
输出为: 可以看到,我们拿到的 ser_1 仍然是一个 Series 类型的对象。左边的 title、rating、stars是index,右边的"欢喜一家人之加油宝贝""4.0分" 等是 values。因为 ser_1 是一个 Series,所以如果我们要拿这一行中的某个数据,比如评分,直接写 ser_1["rating"] 就可以实现。
对比通过行索引取出的行 Series 和 通过列索引取出的列 Series 不难发现,列 Series 的 index 是 DataFrame 的行头,而行 Series 的 index 则是 DataFrame 的列名。
(2)DataFrame 的创建
既然 DataFrame 是一个个 Series 组成的,那自然我们可以用 Series 来构造出 DataFrame。
构造 DataFrame 最常见的方式是用多个行 Series 的形式来创建,不同的行 Series 的长度应该是一致的(因为表格中每一行的元素个数都需要相等)。
# 将列索引保存在 index_arr 变量中
index_arr = ["姓名", "年龄", "籍贯", "部门"]
# 构建小明、小亮、小E的行 Series,并使用我们创建好的 index_arr 作为 Series 的index
ser_xiaoming = pd.Series(["小明", 22, "河北","IT部"], index= index_arr)
ser_xiaoliang = pd.Series(["小亮", 25, "广东","IT部"], index = index_arr)
ser_xiaoe = pd.Series(["小E", 23, "四川","财务部"], index= index_arr)
# 直接将三个 Series 以列表的形式作为 DataFrame 的参数,创建 DataFrame
df_info = pd.DataFrame([ser_xiaoming, ser_xiaoliang, ser_xiaoe])
# 使用 notebook 打印 DataFrame
df_info
输出:
可以看到,表格已经被成功的打印出来,这说明我们已经将内容正确构建出了 DataFrame。
4、基本操作
(1)添加行
DataFrame 提供了 append 的方法,用于添加一行,用法如下:
# 新建一个行 Series,存储在 ser_xiaoh变量中
ser_xiaoh = pd.Series(["小红", 28, "福建", "财务部"], index = index_arr)
# 调用 append 方法添加到DataFrame 中
# 设置 ignore_index 的含义是让 DataFrame 自动生成行索引
# 调用 append 之后,会返回一个新的 DataFrame,我们将其保存回 df_info 变量
df_info = df_info.append(ser_xiaoh, ignore_index= True)
# 查看添加后的DataFrame
df_info
输出后可以看到,小红的记录已经追加到了末尾。
(2)添加列
添加一列一般有两种情况,如果我们要添加的列,所有行的值都相同的话,我们可以直接以单个值赋值给新添加的列 Series 即可。如下所示:
# 直接将新添加的列名当作 DataFrame 的列索引,对其赋新的值
df_info["考核结果"] = "合格"
# 查看
df_info
输出为:
(3)删除行或列
DataFrame 提供了 drop 方法来删除某一行或者某一列。
我们先以删除列举例,比如要删除刚才我们添加的“考核结果”这一列
# labels 是要删除的列名
# axis = 1 代表要删除的是列
# inplace = True 代表删除直接在 df_info 中生效。
df_info.drop(labels = "考核结果", axis=1, inplace= True)
# 查看
df_info
输出为:
接下来是删除行,以删除小 E 这一行为例:
# labels 是要删除行的 index,小E的index是2
# axis = 0 代表要删除的是行
df_info.drop(labels=2, axis=0, inplace=True)
# 查看
df_info
输出结果如下,可以看到,小 E 那一行记录已经被成功删除。
(4)单个单元格的查看与修改
查看单元格:
# loc 属性后面跟中括号,中括号里面第一个元素是行索引,第二个元素是列索引
# 小亮的行索引是1,我们想查看籍贯,所以列索引就是籍贯
df_info.loc[1, "籍贯"]
输出为:
'广东'
学会了查看之后,修改就比较简单了,直接给 loc 属性选出来的单元格赋值即可。
# 对行索引为1,列索引为 籍贯 的单元格赋值,赋值 广西
df_info.loc[1, "籍贯"] = "广西"
# 查看 DataFrame
df_info
输出,可以看到,小亮的籍贯已经被修改为广西。
(5)DataFrame 的排序
在数据分析的任务中,对数据集进行排序是非常常见的诉求。拿我们电视剧评分的数据集来说,可能我们希望分析高分的电影和低分的电影分别都有些什么特征。做这样的分析,首先第一步就是需要将我们的 DataFrame 按评分排序。我们以之前我们从 csv 加载的 DataFrame, df_rating 为例。
DataFrame 提供了 sort_values 方法来实现排序,用法如下。
# by 参数代表要按 rating 这个列索引来排序
# inplace = True 的含义和上面说的一样,代表更新当前的DataFrame,而不是返回一个新的
df_rating.sort_values(by = "rating", inplace=True)
# 查看排序后的 DataFrame
df_rating
输出为:
可以看到,整个 DataFrame 不再是按行头的索引排序,而是按照电视剧的评分从低到高来排序了。
如果想看从高到低呢?自然也是支持的。只需要将是否升序排序的参数:ascending 设置为False 即可。
# 在刚才的基础上,增加 ascending=False,代表按降序排序
df_rating.sort_values(by="rating", inplace=True, ascending=False)
# 查看
df_rating
输出为:
(6)取前 N 个和后 N 个
在排序后,我们对数据表要进行分析,比如对高分进行分析,我们往往需要看多几个条目。但是每次输出 DataFrame 的时候,Notebook 一般只会选择前五个和末尾五个组成摘要进行表格的输出。如果默认的表格打印不满足我们的需求,我们可以使用 DataFrame 的 head 函数和 tail 函数来输出前 N 个和 后 N 个的数据。
举个例子,我们希望分别分析 20 条高分电视剧和 20 条低分电视剧。可以按如下方式实现:
# head 函数返回 DataFrame 的前 N 条记录,N就是函数参数指定的值
# 这里我们指定 20
df_rating.head(20)
输出为:
输出最后的 20 条的原理是类似的,只不过换成 tail 函数。
# tail 函数,返回DataFrame 的末尾的 N 条记录,N就是函数的参数
# 这里的N,我们指定 20
df_rating.tail(20)
输出为:
(7)获取 DataFrame 的行数和列数
很多时候,从数据文件加载为 DataFrame 的时候,我们首先会看这个 DataFrame 有多少行、多少列。 DataFrame 提供了 shape 属性来返回行数和列数的信息。
shape 属性返回一个元组,这个数据结构我们之前没有介绍过,不过你可以简单把他当一个列表用即可,shape 属性返回的元组有两个元素,第一个就是行数,第二个就是列数。
比如那 df_rating 这个 DataFrame 为例,打印其行列数信息,代码如下:
# shape 属性,返回一个元祖,第一个是行数,第二个元素是列数
shape = df_rating.shape
# 打印行数和列数
print("行数:", shape[0])
print("列数:", shape[1])
输出为:
标签:rating,index,Python,Series,DataFrame,索引,df,基本操作 From: https://blog.51cto.com/jiangyi/9439401更多技术文章欢迎关注:服务端技术精选