查看原文
其他

Python 教学 | Pandas 表格数据行列变换

分享技巧的 数据Seminar 2023-06-12

目录

一、前言

二、行、列的增加和删除

  (一)增加列(字段)

  (二)删除列

  (三)增加行

  (四)删除行

三、表格转置

四、数据展开与合并

  (一)多行合并为一行

  (二)一行展开为多行

五、总结

六、Python教程

本文共6779个字,阅读大约需要17分钟,欢迎指正!

Part1前言

Pandas 是专注于表格数据处理的 Python 第三方库,能帮助我们完成各种各样的表格数据操作。上期文章我们介绍了数据清洗中使用 Pandas 处理缺失值和重复值的方法,在常见的数据清洗中,除了针对数据值做处理,有时候也需要对表格的结构做变换操作,最基本的有添加/删除行或列,以及一行变多行、多行并一行、字段之间计算等操作,本期文章我们就向大家介绍如何使用 Pandas 对表格数据做一些基本的行列变换。

本教程基于 pandas 1.5.3 版本书写。本文中所有 Python 代码均在集成开发环境 Visual Studio Code (VScode) 中使用交互式开发环境 Jupyter Notebook 中编写,本文分享的代码请使用 Jupyter Notebook 打开。

💡后台回复关键词“20230609”即可获取本文所有演示代码以及演示用的数据。

Part2行、列的增加和删除

先读取演示用的数据表。

import pandas as pd     # 导入 pandas 库
data = pd.read_excel('./2、工业互联网专题数据库2000-2020.03企业时间分布统计数据.xlsx'# 读取演示数据
data     # 输出查看演示数据


(一)增加列(字段)

处理表格数据时经常需要添加或者删除字段,在 Pandas 中,添加字段的方式不止一种,下面我们来介绍一下。

(1)在表格尾端添加一列

在 Pandas 基础中,我们曾介绍过表示表格(DataFrame,数据框)中一个字段的代码是表格变量名[字段名],例如上文读取的表格数据变量名为data,那么获取年份这一字段的代码就是data['年份'],得到的是一个一维 Series,实际上除了这种表示方法,使用表格变量名.字段名同样可以表示一个字段,例如data.年份。不过使用后者表示字段时需要注意,如果字段名是字符型,则不可以使用引号引起来,且字段名中不能含有空格符.半角括号等在 Python 中具有特殊意义的字符。知道如何表示一个字段后,添加字段也就轻而易举了,我们直接将新添加字段的值赋给新字段即可,不过只能使用表格变量名[字段名]的方式来添加字段,例如下面是添加一个新字段“备注”,取值为“无”的代码。

# 在数据尾端添加一个新字段“备注”, 该字段的所有值都是‘无’
data['备注'] = '无'     # 不可以使用 data.备注='无'
data   # 输出查看 data

这种添加字段的方式在添加时会为整个字段赋予一个指定值,例如上述代码中的'无',这种方式常用于先增加字段,后续再根据情况填充新字段。如果我们想在创建一个新字段的时候,为每一行赋予指定值,可以直接将包含值的列表赋值给新字段,但是需要注意,列表中元素的个数必须与数据表的行数保持一致,即每一行的值都必须指定才行,代码如下。

# 创建新字段时,为每一行设置指定值
data['备注'] = ['''''该年份数据有缺失''''''''',
              '''''该年份数据有缺失''''''''',
              '''''''''''''该年份数据有缺失']   # 数据表共 21 行,则需要填入 21 个值
data   # 输出查看 data


💡 注意,以上两种方式不仅可以用来添加新字段,也可以修改已有字段的内容。

(2)通过计算得到新字段

除了以上两种方式外,我们还可以根据字段之间的运算得到新字段,例如我们想生成一个新字段“净增加企业数”,这个字段的内容是“企业成立数”与“企业死亡数”相减的结果,那么可以使用下面的代码。

# 通过字段之间的计算得到新字段
data['净增加企业数'] = data['企业成立数'] - data['企业死亡数']
data

使用这种(计算)方式生成新字段时需要注意,参与计算的字段之间必须是可以进行运算的,例如两个字段中的值都是数值型,那么它们之间就可以进行加、减、乘、除、幂等基本运算,但如果两个字段中的值不是可以进行运算的,例如字符型和浮点型就无法进行运算,那么运算操作就无法进行。因此需要特别注意参与计算的两个字段,是否存在缺失值,其内部的值是不是可以两两运算。如果有个别的特殊值导致字段之间不能运算,我们还可以使用函数的方式去做处理,不过那是后续文章才要讲的内容。

(3)指定位置插入字段

前面介绍的几种方式都是在表格的尾端创建新字段,很多时候表格的字段之间是有顺序的,添加新字段也要在指定的位置进行。在 Pandas 中,insert()函数就是用来在指定位置插入字段的,使用方法如下。

表格变量名.insert(插入字段的位置, 插入字段的名称, 插入字段的值)

上述伪代码中,插入字段的位置是指待插入字段所在的顺序(默认从 0 开始计算),例如当我们想在演示数据中企业死亡数之后插入一个字段当年净增加企业数,其值是企业成立数字段与企业死亡数字段的差,那么就可以使用下面的代码。

# 先在指定位置(序号为 3)插入一个空字段
data.insert(3, '当年净增加企业数''')
# 再将计算结果赋值给该字段
data['当年净增加企业数'] = data['企业成立数'] - data['企业死亡数']
data

如果你的表格中字段数量太多,想要快速获取某个字段的序号来做参照,可以使用下面的代码。

# 获取“备注”字段的位置,注意这个位置是从 0 开始计算的
data.columns.get_loc('备注')   # 得到:5

(二) 删除列

在上一期介绍处理缺失值和重复值的文章中,我们提到删除缺失值所在行或列使用的是dropna()函数,而在这里,直接删除行或列的则是drop()函数。两者的区别在于前者是根据表格内数据缺失的情况自动删除数据,而后者是用来删除指定数据行或数据列的。drop()函数的常用参数如下表所示。

例如删除“备注”字段时就可以使用下面的代码。

## 删除“备注”字段,且使删除操作在原数据上生效
# 方法 1
# data.drop(columns='备注', inplace=True) # 或者 data = data.drop(columns='备注'), 但要注意赋值操作和 inplace 参数不可同时使用,否则直接丢失原数据
# 方法 2
data.drop('备注', axis=1, inplace=True) # 或者 data = data.drop('备注', axis=1)
# 方法 3
# data.drop(['备注'], axis=1, inplace=True) # 或者 data = data.drop(['备注'], axis=1)

由于drop()函数默认不会直接修改原数据,所以如果想让删除操作在原数据上生效,就需要主动设置参数inplace=True;或者不设置inplace参数,而是将drop()函数返回的新对象重新赋值给原来的变量名。这段代码中介绍了 6 种删除一个字段的方法,实际操作时使用其中之一即可。如果想要一次性删除表中多个字段,例如删除data中的“当年净增加企业数”和“净增加企业数”两个字段,可以使用下面的代码。

# 删除“当年净增加企业数”和“净增加企业数”两个字段
# 方法 1
# data.drop(['当年净增加企业数', '净增加企业数'], axis=1, inplace=True)  # 或 data = data.drop(['当年净增加企业数', '净增加企业数'], axis=1)
# 方法 2
data.drop(columns=['当年净增加企业数''净增加企业数'], inplace=True)  # 或 data = data.drop(columns=['当年净增加企业数', '净增加企业数'])、
data

(三) 增加行

Pandas 对数据行的增加并不友好,不像增加数据列那样简单方便,最常见的就是在数据的尾端添加一行数据,下面是添加一行数据的代码。

# 方法 1:使用 append 函数,可能会遇到警告,该函数将会在未来的 pandas 版本中移除
# data = data.append({'年份':2021, '企业成立数':5000, '企业死亡数':2000, '企业存续数':250000}, ignore_index=True) # 添加的一行并非真实统计数据,只做演示用
# 方法 2:使用数据切片(数据选取),注意代码中的 21 是增加数据行的索引值,添加的索引必不能是事先存在于 data 中的
data.loc[21] = {'年份':2021, '企业成立数':5000, '企业死亡数':2000, '企业存续数':250000}
data

除了以上这种增加一行的操作之外,还可以一次性将多行数据添加到一张表中,实际上是通过拼接多个表格实现的,这个我们会在后续的文章中介绍。

(四) 删除行

删除数据行与删除数据列使用的都是drop()函数,这一点我们在上文中介绍drop()函数的参数时已经有提到。删除数据列时,使用的是columns参数,或者在设置参数axis=1的前提下使用labels参数;根据上文中的参数列表,我们可以知道,删除数据行应该使用index参数,或者直接使用labels参数(因为axis参数默认为 0,即默认删除的是数据行)。例如删除索引值为 4,5,6 的数据行可以使用下面的代码。

# 删除索引值为 4,5,6 的数据行,并将删除后的数据赋值给新变量 data_droped
data_droped = data.drop([4,5,6]) # 这里使用的是 labels 参数,与使用 index 参数是一样的效果,因为 axis 的默认值为 0
# 删除后的数据就不再文中展示了

除了直接传入具体的行索引值列表,我们还可以借助数据筛选来获取索引值,并以此达到删除符合条件的数据,例如可以使用下面的代码来删除 2010 年之前的数据。

# 删除 2010 年之前的数据
data_Before2010 = data[data['年份'] < 2010]
# 根据筛选结果的索引值进行删除
data_After2010 = data.drop(data_Before2010.index)  # 也可以直接这样写:data_After2010 = data.drop(data[data['年份'] < 2010].index),这样只需要一句代码就可以了
# 查看删除后的数据值
data_After2010

由于 Pandas 中表格数据类型 DataFrame 的行索引值不会自动变化,所以增加、删除数据行可能会导致行索引变得不连续,如果需要让数据的索引重新变得连续,可以使用reset_index()函数来重置索引,代码如下。

# 重置 data_After2010 的行索引,使其从0 开始且连续
# drop=True 参数表示重置索引后,原来的索引会被删除,如果不设置此参数,原来的索引值会自动添加到数据中,字段名为“index”
# 同 drop() 函数一样,reset_index() 也会返回一个新对象,而不是直接修改原数据,如果希望重置索引操作在原数据上生效
# 可以使用赋值方式,或者在 reset_index() 中设置参数 inplace=True
data_After2010 = data_After2010.reset_index(drop=True) 
data_After2010   # 查看重置索引后的值

Part3表格转置

什么是转置?首先,转置是一个数学名词,是线性代数中矩阵的一种变换。我们常用的表格数据实际上就是一种矩阵,所以也有转置操作,那么转置到底是一种怎么样的数据操作呢?在表格中,转置就是表格沿着数据的左上角与右下角形成的对角线进行翻转,最后转置前数据的第 n 行就会变成转置后数据的第 n 列,如下图所示。

有时候遇到一些需要做行列转换的数据,就可以使用 Pandas 来对数据做转置操作,转置后数据框(DataFrame)的行索引和列索引(即字段名)也会互换位置,下面是对上文中表格数据data_After2010做转置的代码。

# 代码【数据框.T】就可以返回转置后的数据了 
data_转置 = data_After2010.T
data_转置

Part4数据展开与合并

一些时候过多的数据都被存放在一个单元格中,为了让数据更清晰,或者为了匹配数据,需要对数据做“展开”,将一行数据变为多行数据;而有时候为了减少数据量,又要去做相反的处理,将多行数据合并到一行。下面我们以数据变量清单表为例,演示如何进行上述操作,下面先读取演示数据。

# 读取演示数据
DATA = pd.read_excel('./1、工业互联网变量清单.xlsx', usecols=['表名称''字段名称'])

💡 如果 Excel 表中存在合并的单元格,那么经过 Pandas 读取后,合并区域中只有左上方的小单元格内有值,其余区域都是空值,如上图所示。

(一) 多行合并为一行

我们的目的是将上图中“字段名称”列中的值根据“表名称”列进行合并。也就是说根据第一列对第二列做合并,那么多行合并一行的代码如下。

# 由于【表名称】字段的原始数据是合并的单元格,所以合并前需要做向下填充操作
# 向下填充,就是在一列数据中使用上一个非空值来填充下面的缺失值,操作方式如下
DATA['表名称'] = DATA['表名称'].ffill()

# 然后再进行合并数据行
# 先定义拼接函数,并对字段进行去重
def concat_func(x):
    return pd.Series({'字段名称':'、'.join(x['字段名称'])})
# 分组聚合 + 拼接
DATA_合并 = DATA.groupby(DATA['表名称']).apply(concat_func).reset_index()
DATA_合并    # 合并后数据的顺序会乱

(二) 一行展开为多行

除了能够将多行数据合并为一行,Pandas 还可以将一行数据展开为多行数据,而且更加简单,下面我们来对上图所示数据注意一个反向的展开操作,代码如下。

# 第一步,先使用匿名函数将可展开的字符转为列表
DATA_合并['字段名称'] = DATA_合并['字段名称'].apply(lambda x: x.split('、'))
# 第二步,使用 explode() 函数对【字段名称】列做展开操作
DATA_展开 = DATA_合并.explode('字段名称')
DATA_展开

以上就是本期 pandas 表格行列变换的全部内容。

Part5总结

Pandas 在处理表格数据方面是一个重要工具,除了完成一些常见的筛选,分析操作,当需要重构数据或者进行一些较复杂的数据处理时,必然需要使用更加精细的数据操作。本文介绍的正是在行列数据处理的一些技巧,熟悉这些技巧能让我们在数据处理中更加游刃有余。

Part6Python教程

 (向下滑动查看更多)



星标⭐我们不迷路!想要文章及时到,文末“在看”少不了!

点击搜索你感兴趣的内容吧

往期推荐


Python 教学 | Pandas 缺失值与重复值的处理方法

Python 教学 | Pandas 妙不可言的条件数据筛选

Python 教学 | Pandas 数据索引与数据选取

Python 教学 | 数据处理必备工具之 Pandas(数据的读取与导出)

第一届“商泰杯”中国普惠金融数据库应用大赛来啦!





数据Seminar




这里是大数据、分析技术与学术研究的三叉路口


文 | 《社科领域大数据治理实务手册》


    欢迎扫描👇二维码添加关注    

点击下方“阅读全文”了解更多

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存