提高Cronbach Alpha python numpy代码的性能

5

我写了一些用于计算Cronbach Alpha的代码,但不太擅长使用lambda函数。是否有一种方法可以通过使用lambda代替svar()函数并使用numpy数组来减少代码并提高效率,从而消除一些for循环?

import numpy as np


def svar(X):
    n = float(len(X))
    svar=(sum([(x-np.mean(X))**2 for x in X]) / n)* n/(n-1.)
    return svar


def CronbachAlpha(itemscores):
    itemvars = [svar(item) for item in itemscores]
    tscores = [0] * len(itemscores[0])
    for item in itemscores:
       for i in range(len(item)):
          tscores[i]+= item[i]
    nitems = len(itemscores)
    #print "total scores=", tscores, 'number of items=', nitems

    Calpha=nitems/(nitems-1.) * (1-sum(itemvars)/ svar(tscores))

    return Calpha

###########Test################
itemscores = [[ 4,14,3,3,23,4,52,3,33,3],
              [ 5,14,4,3,24,5,55,4,15,3]]
print "Cronbach alpha = ", CronbachAlpha(itemscores)

1
为什么在这里使用Lambda表达式会有帮助? - user2357112
3
对于那些对为什么它总是接近1.0感到极度困惑的人,你需要注意这里的itemscores是n*p,其中n(每行)是项目(问题),p(每列)是受访者的答案。如果你像我一样使用pandas,很可能每行都是受访者,每列都是项目。因此,要使用此函数,您需要转置数据框或修改函数。还要注意,在Python 2.7中,你需要从未来导入除法(division)或用float()将分母括起来。 - Julien Marrec
3个回答

10
def CronbachAlpha(itemscores):
    itemscores = numpy.asarray(itemscores)
    itemvars = itemscores.var(axis=1, ddof=1)
    tscores = itemscores.sum(axis=0)
    nitems = len(itemscores)

    return nitems / (nitems-1.) * (1 - itemvars.sum() / tscores.var(ddof=1))

NumPy内置了方差函数。指定 ddof=1 使用 N-1 作为分母,得到样本方差。还有一个内置的 sum 函数。


1
谢谢分享!我基于你的代码为这个 cronbach_alpha 发布了一个库,链接为 https://github.com/anthropedia/tci-stats。希望以后能够进一步丰富它。 - vinyll

1
与其他答案相同,只不过更具有Python风格。 X是一个数据矩阵--也就是说,行是样本,列是项目。 X可以是numpy数组或pandas DataFrame。
def cronbach_alpha(X):
    num_items = X.shape[1]
    sum_of_item_variances = X.var(axis=0).sum()
    variance_of_sum_of_items = X.sum(axis=1).var()
    return num_items/(num_items - 1)*(1 - sum_of_item_variances/variance_of_sum_of_items)

(不必指定,因为该术语出现在分母和分子中,并互相抵消。)

1

正如Julien Marrec所提到的,我建议对CronbachAlpha进行以下重构:

def CronbachAlpha(itemscores):
    # cols are items, rows are observations
    itemscores = np.asarray(itemscores)
    itemvars = itemscores.var(axis=0, ddof=1)
    tscores = itemscores.sum(axis=1)
    nitems = len(itemscores.columns)

    return (nitems / (nitems-1)) * (1 - (itemvars.sum() / tscores.var(ddof=1)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接