5. dataframe 函数应用

DataFrame 可以使用apply 函数对行或者列的数据进行修改,在apply里传入一个函数,apply的作用是让每一行或者每一列的数据都应用传入的函数进行处理。此外,还有pipe和applymap函数,他们功能类似但应用范围不同,下面是他们的应用范围:

  1. 表级函数应用:pipe()
  2. 行列级函数应用: apply()
  3. 元素级函数应用:applymap()

具体使用哪一种,取决于所操作的对象是 DataFrame,还是 Series ;是行、列,还是元素。

1. 表级函数应用 pipe()

我用最简单的一个例子来讲解pipe函数的链式编程

import pandas as pd


data = [
    {'语文': 90, '数学': 92},
    {'语文': 98, '数学': 87},
    {'语文': 87, '数学': 90},
    {'语文': 90, '数学': 98},
]

def add_sum_column(df):
    # 添加总分列
    result = df.copy()
    columns = result.columns.tolist()
    if '平均值' in columns:
        columns.remove('平均值')
    result['总分'] = result[columns].sum(axis=1)
    return result

def add_mean_column(df):
    # 添加平均值列
    result = df.copy()
    columns = result.columns.tolist()
    if '总分' in columns:
        columns.remove('总分')
    result['平均值'] = result[columns].mean(axis=1)
    return result

df = pd.DataFrame(data, index=['小明', '小红', '小刚', '小丽'])
df_sum = add_sum_column(df)
df_mean = add_mean_column(df_sum)

print(df_mean)

程序输出结果

    数学  语文   总分   平均值
小明  92  90  182  91.0
小红  87  98  185  92.5
小刚  90  87  177  88.5
小丽  98  90  188  94.0

最初的DataFrame并没有总分和平均值这两列,我在示例中定义了两个函数,分别增加总分列和平均值列,之后分两次调用函数。所谓链式编程,简单讲就是把多次函数调用连接在一起,方便代码编写和阅读,使用pipe进行链式编程,示例代码如下

df = pd.DataFrame(data, index=['小明', '小红', '小刚', '小丽'])
result = df.pipe(add_sum_column).pipe(add_mean_column)
print(result)

pipe函数传入的应用函数,可以是自定义函数,也可以是第三方函数,这个函数必须返回处理后的DataFrame, 多个函数要使用多个pipe函数进行调用。

2. 行列级函数应用 apply()

对每一行或者每一列数据应用apply函数进行计算,比如计算各学科的平均值,计算学生各个科目的平均值

import pandas as pd
import numpy as np


data = [
    {'语文': 90, '数学': 92},
    {'语文': 98, '数学': 87},
    {'语文': 87, '数学': 90},
    {'语文': 90, '数学': 98},
]

df = pd.DataFrame(data, index=['小明', '小红', '小刚', '小丽'])
print(df.apply(np.mean))    # 逐行进行操作, 求语文和数学的平均值
print(df.apply(np.mean, axis=1))    # 逐列进行操作, 求每个学生的各科平均值

程序输出结果

数学    91.75
语文    91.25
dtype: float64

应用apply进行操作时,其结果容易让我们产生误解,比如axis=1时,我代码注释里写的是逐行进行操作,那么结果难道不应该是求每一列的平均值么,怎么变成了求每一行数据的平均值?关于这个问题,我教大家一个好的方法来理解。当axis=0时,是逐行操作,因此最终计算出一行新的数据,那么就只能是计算各个学科的平均值, axis=1时,逐列进行操作,最终计算出一个新的列,那么这个新的列只能是以学生做维度,计算他们各个科目的平均值,这样理解是不是就容易一些了呢

3. 元素级函数应用, applymap()

applymap是元素级应用函数,它会对每一个元素产生作用

import pandas as pd

data = [
    {'语文': '90', '数学': '92'},
    {'语文': '98', '数学': '87'},
    {'语文': '87', '数学': '90'},
    {'语文': '90', '数学': '98'},
]

df = pd.DataFrame(data, index=['小明', '小红', '小刚', '小丽'])
print(df['语文'])

程序输出结果是

小明    90
小红    98
小刚    87
小丽    90
Name: 语文, dtype: object

dtype是object, 而不是我们期望的int64,我们可以使用applymap将所有数据都转成int类型

df = pd.DataFrame(data, index=['小明', '小红', '小刚', '小丽'])
df = df.applymap(lambda x: int(x))
print(df['语文'])

程序输出结果

小明    90
小红    98
小刚    87
小丽    90
Name: 语文, dtype: int64

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案