pandas教程:Techniques for Method Chaining 方法链接的技巧-灵析社区

清晨我上码

12.3 Techniques for Method Chaining(方法链接的技巧)

对序列进行转换的时候,我们会发现会创建很多再也不会用到的临时变量(temporary variable)。比如下面的例子:

df = load_data()
df2 = df[df['col2'] < 0]
df2['col1_demeaned'] = df2['col1'] - df2['col1'].mean()
result = df2.groupby('key').col1_demeaned.std()

这里我们不使用任何真实数据,这个例子说明了一些新方法。首先,DataFrame.assign方法是一个函数,它可以作为列赋值方法df[k] = v的替代品。它不会修改原有的对象,而是会返回一个带有修改标识的新DataFrame对象。所以下面两个方法是相等的:

# Usual non-functional way 
df2 = df.copy() 
df2['k'] = v

# Functional assign way 
df2 = df.assign(k=v)

在原始对象上直接进行赋值比用assign会更快一些,但是assign可以使用更方便的方法链接(method chaining):

result = (df2.assign(col1_demeaned=df2.col1 - df2.col2.mean())
         .groupby('key')
         .col1_demeaned.std())

需要记住的是,当使用方法链接的时候,你可能会需要引用临时对象。在之后的例子,我们不能引用load_data的结果,除非它被赋值给临时变量df. 。为了做到这一点,assign和其他一些pandas函数接受像函数一样函数参数(function-like arguments),也被称作为可调用(callables)。

为了演示callables,考虑上面例子里的一个片段:

df = load_data() 
df2 = df[df['col2'] < 0]

这句可以被写为:

df = (load_data()[lambda x: x['col2'] < 0])

在这里,load_data的结果没有赋值给参数,所以传入[]中的函数被绑定到了绑定到了在某个链接状态下的对象上(so the function passed into [] is then bound to the object at that stage of the method chain)。

我们可以把整个序列携程一行链接表达式:

result = (load_data()
          [lambda x: x.col2 < 0]
          .assign(col1_demeaned=lambda x: x.col1 - x.col1.mean())
          .groupby('key')
          .col1_demeaned.std())

我们可以把代码写成这种风格,但也可以分解成为步来写,这样可读性会更高。

1 The pipe Method(pipe方法)

我们可以利用pandas内建的函数和一些用callables实现的方法链接,做很多事情。不过,有时候我们想要用自己的函数或一些第三方库里的函数。这就是pipe方法出现的原因。

假设有一系列函数调用:

a = f(df, arg1=v1) 
b = g(a, v2, arg3=v3) 
c = h(b, arg4=v4)

当使用函数来接受或返回Series或DataFrame对象的时候,我们可以把上面的利用pipe重写为:

result = (df.pipe(f, arg1=v1)
          .pipe(g, v2, arg3=v3) 
          .pipe(h, arg4=v4))

f(df)和df.pipe(f)是一样的,但是pipe能让链接调用更简单。

pipe一个有用的模式是生成一系列可重复的函数操作。例如,考虑计算两个组的平均值的差:

g = df.groupby(['key1', 'key2']) 
df['col1'] = df['col1'] - g.transform('mean')

假设我们想要能对不止一个组进行减值,只要改变分组键(group key)即可。除此之外,我们可能想要把这种转换用方法链接的形式实现。这里有一个例子:

def group_demean(df, by, cols):
    result = df.copy() 
    g = df.groupby(by) 
    for c in cols:
        result[c] = df[c] - g[c].transform('mean') 
    return result

上面的也可以写为:

result = (df[df.col1 < 0] 
          .pipe(group_demean, ['key1', 'key2'], ['col1']))


阅读量:218

点赞量:0

收藏量:0