Pandas中使用apply方法(参数详解)

时间:2022-07-18 阅读:3106 评论:0 作者:魏勇

apply()

apply方法可以沿着DataFrame数据的行、列执行回调函数

首先看一下apply方法的参数,apply方法返回的数据类型为Series或DataFrame

apply(func, axis=0, raw=False, result_type=None, args=(), **kwargs)  -> Series或DataFrame

注意:调用apply方法的必须是DataFrame数据,apply方法并不会改变原始数据

apply方法官方文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html

参数func和axis

func: 回调函数,该函数通常只有一个表示Series数据类型的形参,Series可能是行,也可能是列

axis:0 或 “index” 表示对每一列执行回调函数func, 1或”column”表示对每一行执行回调函数func。默认值为0

假设有如下的DataFrame数据,取变量名为df:

import pandas as pd
obj = {'x': [2, 4], 'y': [6, 8]}
df = pd.DataFrame(obj)
print(df)
    x    y
0  2    6
1  4    8

该数据中有列名为x、列名为y的数据(也可以说行索引为0、行索引为1的数据),对于其中任意一行(或一列)其数据类型为Series,整个行列的数据类型为DataFrame。

现在我们已经知道了apply方法的前两个参数,也知道了已有数据df,那么我们传入df数据的每一列:

def func(data):
  print(data)

df.apply(func, axis=0)

首先,我们定义了回调函数func,然后调用apply方法并传递参数func和axis,这样df中的每一列数据都会作为参数传递到func函数中处理。因为是对每一列数据进行处理,所以axis为0。当然axis默认值为0,也可以省略为:df.apply(func)。此时,func的参数data表示的是每一列的数据。

执行到上面的代码第4行,可以看到如下按列的输出:

# 第一次列输出,输出x列数据
0    2
1    4
Name: x, dtype: int64
# 第二次列输出,输出y列数据
0    6
1    8
Name: y, dtype: int64

还是最开始数据df,如果传入df数据的每一行,那么应该这样写:

def func(data):
  print(data)

df.apply(func, axis=1)

对于上一次的func和axis参数可以发现,axis的参数变为1,表示函数func的参数data值的是df中的每一行数据。在func中data返回。df调用apply方法好后执行到第4行,可以看到如下按行的输出:

# 第一次行输出, 输出索引为0的行
x    2
y    6
Name: 0, dtype: int64
# 第2次行输出, 输出索引为1的行
x    4
y    8
Name: 1, dtype: int64

通常我们会对每一列(或行)中的数据进行其它运算:

def func(data):
  return data*2   # 将每一列(或行)的数据乘以2
df2 = df.apply(func, axis=0)
print(df2)

# 输出如下:
   x   y
0  4  12
1  8  16

注意:apply方法并不会改变原始数据,因此将df.apply()赋值给了df2

对于上面简单的写法可以使用lambda表达式代替:

df2 = df.apply(lambda data: data*2, axis=0)
print(df2)

# 输出如下:
   x   y
0  4  12
1  8  16

参数raw

raw: 布尔值True或False,默认为False。该参数指明传入回调函数func的data参数是什么数据类型?也就是说df的每一行(或每一列)作为何种数据类型的参数传递到func中。False表示以Series类型传递,True表示以ndaary类型传递。

def func(data):
  print(type(data), data)
df.apply(func, raw=False)
# 以下为执行apply时的输出
<class 'pandas.core.series.Series'> 0    2
1    4
Name: x, dtype: int64
<class 'pandas.core.series.Series'> 0    6
1    8
Name: y, dtype: int64

上面的样例中,显式的设置了raw=False(当然raw默认为False,可以省略),通过打印type(data)可以看到数据类型为Series。

下面的样例中,显式的设置raw=True,查看打印的数据类型为ndarray。

def func(data):
  print(type(data), data)
df.apply(func, raw=True)
# 以下为执行apply时的输出
<class 'numpy.ndarray'> [2 4]
<class 'numpy.ndarray'> [6 8]

参数result_type

result_type: 该参数仅在axis=1时有效可用,执行func函数后,将处理后的行(或列)数据转变为何种数据类型。默认值为None,它还要其它三种值,其含义如下:

  • “expand”: 将类似列表的数据将转变为列
  • “reduce”: 尽可能的将数据作为Series数据类型返回
  • “broadcast”: 将数据填充至DataFrame的原始结构,原始的索引index和列column将被保留
  • “None”: 默认值。 1.类似列表的数据将作为Series返回;2.如果func返回的就是Series类型数据,则该列数据将被添加到df的末尾(即增加一列数据)

参数args和kwargs

args: 该参数是一个元组。如果func有其它位置参数,那么必须放在这里,

**kwargs:该参数是一个字典。如果func有其它关键字参数,那么必须放在这里。

例如:func含有其它位置参数z1、 z2:

def func(data, z1, z2):
  return data+z1+z2
df2 = df.apply(func, args=(3,4)) # 注意axis默认为0, z1的值为3, z2的值为4
print(df2)
    x   y
0   9  13
1  11  15

例如:func含有位置参数z1、z2和一个关键字参数a1、a2:

def func(data, z1, z2, a1=10, a2=11):
  return data+z1+z2-a1-a2
kwargs = {'a1':5, 'a2':6}
df2 = df.apply(func, args=(3,4), **kwargs) # func中的参数:z1为3, z2为4, a1为5, a2为6 (如果不传递a1或a2,则a1值为默认值10、a2值为默认值11)
print(df2)
   x  y
0 -2  2
1  0  4

注意:当回调函数func既有args也有kwargs参数时,调用apply时传递的参数并不必须和定义时一样。例如:

def func(data, z1, z2, a1=10, a2=11):
  return data+z1+z2-a1-a2
df2 = df.apply(func, args=(3,4,5)) # 并不会报错
print(df2)
   x  y
0 -7 -3
1 -5 -1

在上面的例子中,func在定义时既有args参数(z1,z2)也有kwargs参数(a1,a2),但是再调用apply时,我们仅仅给args参数进行赋值,而且运算程序也没有报错,这是因为kwargs参数有默认值,kwargs参数在没有传参时会使用默认值。args=(3,4,5)中的3、4分别传递给了z1、z2,而5传递给了a1,由于没有给a2传递数据,因此a2会使用默认值11。

假如进行如下调用,则会报错:

df.apply(func, args=(3,4,5,6,7))
TypeError: func() takes from 3 to 5 positional arguments but 6 were given

因为func中除了第一个参数外(第一个参数不需要显式传递),仅定义了4个参数(z1, z2, a1, a2),但是args中传递了5个参数,因此args中的前4个参数可以传递,但是args中的第5个数据由于func并没有定义相关参数,所以会报错。

本文链接: https://django.org.cn/?id=5 转载请注明出处!

下一篇: zabbix配置jmx监控
评论区 交流一下吧!

共有0条评论来说两句吧...

欢迎 发表评论: