Pandas 使用小技巧(DataFrame篇)

5,142 阅读4分钟

前言

最近经常用到 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() 方便!