我有一个包含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])
但使用应用函数有更好的方法吗?
答案 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_rare
和using_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)