Pandas实现列表分列与字典分列的三个实例
大家好,我是小小明,本人非常擅长解决各类复杂数据处理的逻辑,包括各类结构化与非结构化数据互转,字符串解析匹配等等。
至今已经帮助很多数据从业者解决工作中的实际问题,如果你在数据处理上遇到什么困难,欢迎与我交流。
上次我分享了一道基础题N种解题思路,其中一种读取数据的过程涉及到列表分列,详见:https://blog.csdn.net/as604049322/article/details/112760894
这次我将分享三个实际案例,让大家看看列表分列的一些实际应用。
首先,我们先导包并设置Pandas显示参数:
import pandas as pd
pd.set_option("display.max_colwidth", 100)
正则提取并分列
需求:
读取数据:
df = pd.read_excel("正则提取与分列.xlsm", usecols=[0])
df.head()
结果:
补回原因 | |
---|---|
0 | 核实断网时间;20190128至20190217,20190223至20190311,20190407至20190622号无上网记录,协商补回3个月21天 |
1 | 核实断网时间;2019.06.20到2019.07.22无上网记录,断网1个月3天 |
2 | 核实断网时间从20190130到20190322,20190414到20190719无上网记录,断网5个月7天 |
3 | 核实断网时间:20190312到20190802号无上网记录,断网4个月20天 |
4 | 核实断网时间:2019.03.29到2019.06.29无上网记录,协商补回3个月 |
实现代码:
result = df.copy()
result["tmp"] = result["补回原因"].str.findall("([\d.]+[到至][\d.]+)")
result = result.agg({"补回原因": lambda x: x, "tmp": pd.Series}).droplevel(0, axis=1)
result.head()
结果:
补回原因 | 0 | 1 | 2 | |
---|---|---|---|---|
0 | 核实断网时间;20190128至20190217,20190223至20190311,20190407至20190622号无上网记录,协商补回3个月21天 | 20190128至20190217 | 20190223至20190311 | 20190407至20190622 |
1 | 核实断网时间;2019.06.20到2019.07.22无上网记录,断网1个月3天 | 2019.06.20到2019.07.22 | NaN | NaN |
2 | 核实断网时间从20190130到20190322,20190414到20190719无上网记录,断网5个月7天 | 20190130到20190322 | 20190414到20190719 | NaN |
3 | 核实断网时间:20190312到20190802号无上网记录,断网4个月20天 | 20190312到20190802 | NaN | NaN |
4 | 核实断网时间:2019.03.29到2019.06.29无上网记录,协商补回3个月 | 2019.03.29到2019.06.29 | NaN | NaN |
分步解析:
df["tmp"] = df["补回原因"].str.findall("([\d.]+[到至][\d.]+)")
df.head(5)
结果:
补回原因 | tmp | |
---|---|---|
0 | 核实断网时间;20190128至20190217,20190223至20190311,20190407至20190622号无上网记录,协商补回3个月21天 | [20190128至20190217, 20190223至20190311, 20190407至20190622] |
1 | 核实断网时间;2019.06.20到2019.07.22无上网记录,断网1个月3天 | [2019.06.20到2019.07.22] |
2 | 核实断网时间从20190130到20190322,20190414到20190719无上网记录,断网5个月7天 | [20190130到20190322, 20190414到20190719] |
3 | 核实断网时间:20190312到20190802号无上网记录,断网4个月20天 | [20190312到20190802] |
4 | 核实断网时间:2019.03.29到2019.06.29无上网记录,协商补回3个月 | [2019.03.29到2019.06.29] |
这步使用正则提取出每个日期字符串,[\d.]+
表示连续的数字或.用于匹配时间字符串,两个时间之间的连接字符可能是到或至。
然后我使用agg函数直接对Datafream分列:
df.agg({"补回原因": lambda x: x, "tmp": pd.Series})
结果:
由于列索引多了一级,所以需要删除:
df.agg({"补回原因": lambda x: x, "tmp": pd.Series}).droplevel(0, axis=1).head()
结果:
补回原因 | 0 | 1 | 2 | |
---|---|---|---|---|
0 | 核实断网时间;20190128至20190217,20190223至20190311,20190407至20190622号无上网记录,协商补回3个月21天 | 20190128至20190217 | 20190223至20190311 | 20190407至20190622 |
1 | 核实断网时间;2019.06.20到2019.07.22无上网记录,断网1个月3天 | 2019.06.20到2019.07.22 | NaN | NaN |
2 | 核实断网时间从20190130到20190322,20190414到20190719无上网记录,断网5个月7天 | 20190130到20190322 | 20190414到20190719 | NaN |
3 | 核实断网时间:20190312到20190802号无上网记录,断网4个月20天 | 20190312到20190802 | NaN | NaN |
4 | 核实断网时间:2019.03.29到2019.06.29无上网记录,协商补回3个月 | 2019.03.29到2019.06.29 | NaN | NaN |
droplevel(0, axis=1)
用于删除多级索引指定的级别,axis=0可以删除行索引,axis=1则可以删除列索引,第一参数表示删除级别0。当然如果列索引存在名称时还可以传入名称字符串,可参考官网文档:
df = pd.DataFrame([
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12]
... ]).set_index([0, 1]).rename_axis(['a', 'b'])
>>> df.columns = pd.MultiIndex.from_tuples([
... ('c', 'e'), ('d', 'f')
... ], names=['level_1', 'level_2'])
>>> df
level_1 c d
level_2 e f
a b
1 2 3 4
5 6 7 8
9 10 11 12
>>> df.droplevel('a')
level_1 c d
level_2 e f
b
2 3 4
6 7 8
10 11 12
>>> df.droplevel('level2', axis=1)
level_1 c d
a b
1 2 3 4
5 6 7 8
9 10 11 12
分组聚合并分列
需求:
首先,读取数据:
df = pd.read_excel("分组聚合并分列.xlsx")
df
结果:
实现代码:
(df.groupby("姓名")["得分"].apply(list).apply(pd.Series).fillna("").rename(columns=lambda x: f"得分{x+1}").reset_index().astype({"得分1":"int8"})
)
结果:
分布解析:
首先将每个姓名的得分聚合成列表,并最终返回一个Series:
df.groupby("姓名")["得分"].apply(list)
结果:
姓名
孙四娘 [7, 28]
看见星光 [88, 28, 23]
看见月光 [69, 10, 87]
老祝 [51, 29]
马青梅 [99]
Name: 得分, dtype: object
当然,这步的标准写法应该是使用Series的内部方法:
df.groupby("姓名")["得分"].apply(lambda x:x.to_list())
使用Series内部方法的性能比python列表方法转换快一些。
作为一个Series就可以通过将每个列表元素转换为Series,从而最终返回一个分列的Datafream:
_.apply(pd.Series)
结果:
注意:
_
在ipython表示上一个输出返回的结果,jupyter还额外支持_num
表示num编号单元格的输出。
_.fillna("")
结果:
fillna表示填充缺失值,传入""表示将缺失值填充为空字符串。
下面重命名一下列名:
_.rename(columns=lambda x: f"得分{x+1}")
结果:
然后还原索引:
_.reset_index()
结果:
发现结果中有一列,不是整数,所以还原成整数(总分100分,8位足够存储):
_.astype({"得分1":"int8"})
结果:
解析json字符串并字典分列
需求:
首先读取数据:
df = pd.read_excel("字典分列.xlsx")
df.head()
结果:
处理代码:
result = df.features.apply(eval).apply(pd.Series)
result["counts"] = df.counts
result
结果:
储存条件 | 品牌 | 推荐理由 | 品种 | 食用方式 | 是否进口 | 特色服务 | 是否有机 | counts | |
---|---|---|---|---|---|---|---|---|---|
0 | 常温 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 33 |
1 | 冷藏 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 24 |
2 | 常温 | 禾煜 | NaN | NaN | NaN | NaN | NaN | NaN | 22 |
3 | 常温 | 妙洁 | NaN | NaN | NaN | NaN | NaN | NaN | 16 |
4 | 冷冻 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 14 |
… | … | … | … | … | … | … | … | … | … |
2083 | 常温 | 乐事 | 够薄够脆 | NaN | NaN | NaN | NaN | NaN | 1 |
2084 | 冷藏 | NaN | 生态种植 | 黄瓜 | NaN | NaN | NaN | 有机 | 1 |
2085 | 冷藏 | NaN | 腥味较淡 | 鲫鱼 | NaN | NaN | 免费宰杀 | NaN | 1 |
2086 | 冷藏 | NaN | 甜脆可口 | 佛手瓜 | NaN | NaN | NaN | NaN | 1 |
2087 | 冷藏 | 叮咚日日鲜 | 全程可追溯 | 猪小排 | NaN | NaN | NaN | NaN | 1 |
2088 rows × 9 columns
浅析:
df.features.apply(eval)
用于将features列的每个json字符串解析为字典对象。
**.apply(pd.Series)
则可以将每个字典对象转换成Series,则可以将该字典扩展到多列,并将原始的Series转换为Datafream。
而result["counts"] = df.counts
则将原始数据的counts列添加到结果列中。
总结
经过三个案例的练习,大家是否已经对Pandas的分列操作比较熟悉呢?
欢迎大家在下方评论区留言你的看法。
Pandas实现列表分列与字典分列的三个实例相关推荐
- Pandas中兼并数组和字典功能的Series 2013-03-24 11:24:00 分类: Python/Ruby In [2]: # 这段代码用于并排显示多个Series对象 from it
Pandas中兼并数组和字典功能的Series 2013-03-24 11:24:00 分类: Python/Ruby In [2]: # 这段代码用于并排显示多个Series对象 from iter ...
- PANDAS面板数据转换为dict字典数据
我们来总结几种将dataframe转换为字典的方法.1.使用 to_dict() 函数将 Pandas DataFrame 转换为字典Pandas to_dict() 函数将一个 DataFrame ...
- python字典、列表、元祖使用场景_python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍...
python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍 一丶元祖 1.元祖简介 元祖跟列表类似.只不过是有区别的. 如下: tuple(元祖英文) 跟列表类似, 元素不能 ...
- pandas将列表list插入到dataframe的单元格中、pandas使用read_csv函数读取文件并设置保留数值的前置0( leading zeroes)
pandas将列表list插入到dataframe的单元格中.pandas使用read_csv函数读取文件并设置保留数值的前置0( leading zeroes) 目录
- pandas基于列表内容对dataframe数据行进行筛选(isin函数)实战:Filter DataFrame rows on a list of values
pandas基于列表内容对dataframe数据行进行筛选(isin函数)实战:Filter DataFrame rows on a list of values 目录
- python 列表多行_Python Pandas list列表数据列拆分成多行的方法实现
1.实现的效果 示例代码: df=pd.DataFrame({'A':[1,2],'B':[[1,2],[1,2]]}) df Out[458]: A B 0 1 [1, 2] 1 2 [1, 2] ...
- 列表字符串集合字典的常见方法
列表常用的方法 append用于在列表末尾追加新的对象 a = [1,2,3] a.append(4) print(a) ----执行结果---- [1, 2, 3, 4] count用于统计某个元素 ...
- python列表中字典排序_python中字典排序,列表中的字典排序
python中字典排序,列表中的字典排序 一.使用python模块:operator import operator #首先要导入模块operator x = {1:2, 3:4, 4:3, 2:1, ...
- python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍
目录 python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍.md 一丶字典 1.字典的定义 2.字典的使用. 3.字典的常用方法. python学习第八讲,python ...
最新文章
- 推荐一款最好的服务器备份软件
- Python学习笔记:常用内建模块4:hmac
- Linux下串口编程基础
- 高等数学上-赵立军-北京大学出版社-题解-练习5.6
- ldap协议 java_java如何调用ldap协议【LdapContext】
- 伺服驱动器生产文件_直流伺服系统的组成和控制原理详解
- python中index方法详解_Python中的index()方法使用教程
- socket地址API
- 2021-04-23 商业文章版权协议分类
- 怎样填充潘通颜色_怎样判定润滑脂,锂基脂的好坏?
- 粤嵌星计划打卡第三十二天(对象的销毁和垃圾收集机制)(java实现一个权限管理系统)
- java 车牌号正则_最新车牌号码(包括新能源车牌)正则表达式
- web前端开发面试题(二)
- 2022-2028年中国互联网+纸尿裤行业市场全景评估及发展策略分析报告
- 3 个简单的技巧让你的 vue.js 代码更优雅!
- 商场会员营销小程序-连接会员,赋能商家
- 【Spring MVC】mvc详解
- modem与baseband
- 中文信息处理实验2——基于词表的分词
- 崎岖回归之路 圆明园十二生肖兽首铜像的故事