前言
最近经常用到 Pandas 来进行一些数据的清洗与处理,由于自己对 Pandas 使用的不熟练,导致某些处理过程写得有些复杂,完全没有必要。
也经常一时想不起 Pandans 的某些用法,反复查看文档。
所以,在这里简单记录下自己平时用到的处理过程。
这里没有对 Pandas 的介绍,会持续更新的,仅是个人记录而已,不喜勿喷~
使用环境
jupyter notebook
导入所需包
import pandas as pd
import numpy as np
构建数据1
# 构建数据 学生信息
data = {'编号': ['01', '02', '03', '04'],
'姓名': ['小明', '小红', '小兰', '小张'],
'数学': [80, 90, 60, 90],
'语文': [70, 80, 90, 70]}
df = pd.DataFrame(data)
1、整体修改某列的值
# 现在要求所有学生语文上调 10 分
df_ = df.copy()
df_['语文'] = df_['语文'] + 10
df_
2、修改某列满足条件的值
# 将 语文90分以上的 减10分
df_ = df.copy()
df_.loc[df_['语文']>=90, '语文'] = df_['语文']-10
df_
3、新增一列
# 新增每个学生的平均分
df_ = df.copy()
df_['平均分'] = df_[['数学', '语文']].mean(axis=1)
df_
# 根据其他列的值,给新列赋值,如 分数在60-70是及格...90-100是优秀
def score_level(x):
if x < 60:
return '不及格'
elif x < 70:
return '及格'
elif x < 80:
return '中等'
elif x < 90:
return '良好'
elif x <= 100:
return '优秀'
else:
raise Exception(f'“{x}”该分数有误')
df_ = df.copy()
df_['数学等级'] = df_['数学'].apply(score_level)
df_['语文等级'] = df_['语文'].apply(score_level)
df_
注:这里你可能感觉,“数学”后面应该紧跟“数学等级”,这时只需调整下列的顺序,有两种方式可以实现
# 第一种
df_ = df_.reindex(columns = ['编号', '姓名', '数学', '数学等级', '语文', '语文等级'])
# 第二种
# df_ = df_[['编号', '姓名', '数学', '数学等级', '语文', '语文等级']]
df_
4、新增一行
# 新增每科的平均分
df_ = df.copy()
df_.loc['平均分'] = df[['数学', '语文']].mean()
df_
5、列转行
df_col = df.set_index(['编号', '姓名'])\
.stack()\
.reset_index()\
.rename({'level_2': '科目', 0: '分数'}, axis=1)
df_col
使用到的函数解释:
1. set_index(): 将 '编号', '姓名' 设置为索引;
2. stack():将列索引置为series的二级索引(将'编号', '姓名'当做一级(组合)索引),列值置为值;
3. reset_index():重置索引,数据类型 DataFrame,多了两列 level_2 和 0;
4. rename():修改列索引的名称。
6、行转列
df_row = df_col.set_index(['编号', '姓名', '科目'])['分数']\
.unstack()\
.rename_axis(columns=None)\
.reset_index()
使用到的函数解释:
1. set_index(): 将 '编号', '姓名', '科目' 设置为索引;
2. 然后提取 '分数',数据类型Series;
3. unstack():将Series索引的最后一个索引置为列索引,列值置为值,数据类型DataFrame;
4. rename_axis(columns=None)将列索引的名字设置为None;
5. reset_index() 重置索引,将行索引变为列索引。
关于 stack 和 unstack 的用法图解
注:
1)并不是所有的Series能使用unstack和DataFrame能使用stack、unstack,需要看“值组合”。
如:Series中同一索引啥有重复的值,就会unstack报错:
ValueError: Index contains duplicate entries, cannot reshape。
2)unstack()也可传入一个索引层级序号或名称来拆分一个不同的层级。
7、pivot 行转列
pivot():将一列变换为新的DataFrame中的多列。
DataFrame.pivot(index=None, columns=None, values=None) 方法等价于使用 set_index() 创建分层索引,然后调用 unstack()。
- index:重塑的新表的索引名称是什么;
- columns:重塑的新表的列名称是什么;
- values:用哪一列以填充新表。
本来以为一行代码搞定,结果执行下列代码报错:
df_col.pivot(['编号', '姓名'], '科目', '分数')
ValueError: Length of passed values is 8, index implies 2.
注:若有办法用 pivot 一行解决,请留言~谢谢~
7.1、实现单行索引的行转列
df_col.pivot('姓名', '科目', '分数')
7.2、实现多行索引的行转列
df_col.pivot_table(index=['编号', '姓名'], columns='科目', values='分数')
注:当然 pivot_table 也可以实现指定单列的行转列
8、melt 列转行
pivot() 的反向操作是 melt():将多列合并成一列,产生一个新表。
- id_vars:可选项,不需要被转换的列名,转换后作为行索引;
- value_vars:可选项,需要被转换的现有列,若不指明,除 id_vars 之外的其他列都被转换;
- var_name:默认值 variable,自定义列名名称;
- value_name:默认值 value,自定义列名名称;
- col_level:可选项,若列是MultiIndex,则使用此级别。
df.melt(['编号', '姓名'], var_name='科目', value_name='分数')
故,行列转换还是用 pivot() 和 melt() 方便!