Skip to main content
 首页 » 编程设计

python之pandas DataFrame 每一行中唯一浮点值的均值和 sem 的矢量化计算

2025年05月04日20zhenyulu

我想以矢量化方式计算 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)