Pandas适用于因行而异的参数

时间:2014-11-30 19:58:04

标签: python pandas

我有一个包含50行的数据帧,例如来自R的BCI数据。

import pandas.rpy.common as com
varespec = com.load_data('BCI', 'vegan')

我正在尝试将函数应用于每一行,其中函数的大小为'参数。

def rare(y, size):
    notabs = ~np.isnan(y)
    t = y[notabs]
    N = np.sum(t)
    diff = N - t
    rare = np.sum(1 - comb(diff, size)/comb(N, size))
    return rare

如果size是一个整数,它可以正常工作:

varespec.apply(rare, axis=1, args=(20,))

我想要做的是使大小为50个元素的数组,这些元素都有所不同,因此每行都有一个唯一的大小值。如果我将大小设为50的向量,它会传递整个向量,并且该函数不起作用。我怎么做

varespec.apply(rare, axis=1, args=(size,))

为每一行使用一个独特的大小元素?我可以做循环:

for i in xrange(50):
    rare(varespec.iloc[i,:], size[i])

但使用应用函数有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以将结果表示为整个NumPy数组的计算,而不是通过为rare的每一行调用varespec一次来完成计算:

import pandas as pd
import pandas.rpy.common as com
import scipy.misc as misc
import numpy as np
np.random.seed(1)

def rare(y, size):
    notabs = ~np.isnan(y)
    t = y[notabs]
    N = np.sum(t)
    diff = N - t
    rare = np.sum(1 - misc.comb(diff, size)/misc.comb(N, size))
    return rare

def using_rare(size):
    return np.array([rare(varespec.iloc[i,:], size[i]) for i in xrange(50)])

def using_arrays(size):    
    N = varespec.sum(axis='columns', skina=True)
    diff = (N[:, np.newaxis] - varespec.values).T
    return np.sum(1 - misc.comb(diff, size) / misc.comb(N, size), axis=0)

varespec = com.load_data('BCI', 'vegan')
size = np.random.randint(varespec.shape[1], size=(varespec.shape[0],))

这表示using_rareusing_arrays会产生相同的结果:

expected = using_rare(size)
result = using_arrays(size)
assert np.allclose(result, expected)

In [229]: %timeit using_rare(size)
10 loops, best of 3: 36.2 ms per loop

In [230]: %timeit using_arrays(size)
100 loops, best of 3: 2.89 ms per loop

这利用了scipy.misc.comb可以接受NumPy数组作为输入的事实。因此,您可以调用comb(diff, size),其中diff是一个形状数组(225,50),size是一个形状数组(50,)。由于size仅用于comb的调用,因此只需两次调用comb即可执行所有计算。每行不需要循环。

答案 1 :(得分:0)

您可以将该向量作为列添加到数据框中(如果您愿意,可以在以后删除它):

varespec['size'] = size

然后更改您的rare功能:

def rare(x):
    size = x['size']
    y = x.values[:-1]
    ...

或者,如果您不想更改rare,请将其换行:

def rare_wrapper(x):
    size = x['size']
    y = x.values[:-1]
    return rare(y, size)