我想以矢量化方式计算 pandas DataFrame 每一行中唯一浮点值的平均值(即 numpy.mean)和 sem(即 scipy.stats.sem)。
示例输入:
import pandas as pd
t = pd.DataFrame(data={'c1':[1.,2.,3.,4.],
'c2':[1.,2.,3.,3.],
'c3':[1.,2.,2.,2.],
'c4':[1.,1.,1.,1.]})
t.index.name = 'i'
# unique values: [1] [1,2] [1,2,3] [1,2,3,4]
预期结果:
mean sem
i
0 1.0 NaN
1 1.5 0.500000
2 2.0 0.577350
3 2.5 0.645497
请不要像这样提交非矢量化解决方案:
import numpy as np, scipy.stats as ss
def fun(x):
r = x.transpose()[x.index[0]].value_counts(sort=False).rename('count')
r.index.name = 'value'
y = r.index.values
return pd.DataFrame({'mean':np.mean(y), 'sem':ss.sem(y)}, index=[0])
t2 = t.groupby(t.index.names).apply(fun)
t2.index = t2.index.droplevel(1)
真正的 DataFrame 有 >1e12 行,所以不高效的解决方案是行不通的。
理想情况下,拥有浮点值的唯一性条件(即绝对差异或比率偏离一个)会很棒,但任何有效的解决方案都会很棒。
感谢您的帮助!
请您参考如下方法:
这是一个几乎矢量化的解决方案,唯一的非矢量化操作是创建您的掩码,它大部分是矢量化的,但您必须为每列创建一个。
m = np.column_stack([t[col].duplicated() for col in t])
out = t.mask(m)
pd.DataFrame({'mean': np.mean(out), 'sem':ss.sem(out, nan_policy='omit').data})
mean sem
c1 2.5 0.645497
c2 2.0 0.577350
c3 1.5 0.500000
c4 1.0 0.000000
我没有足够的内存来在你的 DataFrame 上测试这个,但这里有一个 100 万行 DataFrame 的示例:
t = pd.concat([t]*250000)
In [649]: %%timeit
...: m = np.column_stack([t[col].duplicated() for col in t])
...: out = t.mask(m)
...: pd.DataFrame({'mean': np.mean(out), 'sem':ss.sem(out, nan_policy='omit').data})
...:
326 ms ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
