使用Pandas计算累计平均值

4
我有一个如下的数据框(Dataframe):
Name  2001 2002 2003 2004 2005 2006  
Name1  2    5     0    0    4    6  
Name2  1    4     2    0    4    0  
Name3  0    5     0    0    0    2  

我希望使用 pandas 计算每一行的累计平均值,但是在计算平均值时,需要忽略数值为零的情况。
期望得到以下输出结果。
Name  2001  2002  2003  2004  2005  2006  
Name1  2    3.5    3.5  3.5   3.75  4.875  
Name2  1    2.5   2.25  2.25  3.125 3.125  
Name3  0     5     5     5    5     3.5  

请您检查一下数学,确保我们在同一个页面上 :-) - cs95
看起来我的数学没错,我们来看第一行,在2005年((3.5+4)/2) = 3.75,而不是3.66。 - Anji
我理解了,这与我所想的累积平均值有些不同。感谢您的澄清。 - cs95
@cs95,谢谢你的帮助,你有任何想法如何实现这个吗? - Anji
1
迭代地进行计算,因为下一个值取决于上一次迭代的计算值。如果您担心速度问题,您可能应该考虑使用numba或cython。 - cs95
尝试使用Pandas的cumsum函数,它应该可以正常工作。 - cerebral_assassin
3个回答

3
首先,根据您的评论,在您的计算中似乎存在一个数学问题。 如果在第一行中您取3.5(这是您称之为当前累积值)加上第一行中2005年的价值4,并得到--> (3.5+4)/2= 3.75, 那么在第二行列2005处就存在错误。 实际上,那里应该是 (2.25 + 4)/2 = 3.125。您所写的是3.175。
现在我相信有更好的方式来实现我的解决方案,但我理解您需要什么。
def cumulative_av(x):
    b=[]
    b.append(x[0])
    for i in range(1,len(x)):
        if(x[i]!=0 and b[-1]!=0):
            b.append((x[i]+b[-1])*0.5)
        elif(x[i]!=0 and b[-1]==0):
            b.append(x[i])
        elif(x[i]==0 and b[-1]!=0):
            b.append(b[-1])
        elif(x[i]==0 and b[-1]==0):
            b.append(0)

    return(b)


apd2=pd.DataFrame(columns=["2001", "2002", "2003", "2004", "2005", "2006"])
for i in range(3):
    apd2.loc[i]=cumulative_av(apd.loc[i,].to_list())

"apd"是您最初的pandas数据帧。cumulative_av是一个函数,生成了您定义的内容(在我看来,这是一个非常奇怪的函数)。

这里是我的代码结果:

    2001    2002    2003    2004    2005    2006
0   2.0     3.5     3.50    3.50    3.750   4.875
1   1.0     2.5     2.25    2.25    3.125   3.125
2   0.0     5.0     5.00    5.00    5.000   3.500

0
def cumavg(s):
    avg=[s[0]]
    for i in range(1,len(s)):
        if s[i]!=0:
            if avg[i-1] ==0:
                avg.append(s[i])
            else:    
                avg.append((s[i]+avg[i-1])/2)
        else:
            avg.append(avg[-1])
    return np.array(avg)
df.apply(lambda s:cumavg(s),axis='columns')

1
这将计算所有数字,但应排除 0 - villoro
很抱歉我误读了你的问题,我会再次尝试并提供答案。 - Mohammed Khalid
现在它计算出了正确的输出,但正如@Fabrizio所提到的,您有一些错误的计算。 - Mohammed Khalid

0

给定以下数据框:

import pandas as pd
data = {
    '2001': {'Name1': 2, 'Name2': 1, 'Name3': 0},
    '2002': {'Name1': 5, 'Name2': 4, 'Name3': 5},
    '2003': {'Name1': 0, 'Name2': 2, 'Name3': 0},
    '2004': {'Name1': 0, 'Name2': 0, 'Name3': 0},
    '2005': {'Name1': 4, 'Name2': 4, 'Name3': 0},
    '2006': {'Name1': 6, 'Name2': 0, 'Name3': 2}
}
df = pd.DataFrame(data)

你需要执行一个cumsum(按列计算,所以axis=1),然后将其除以所有非0元素的cumsum

可以使用以下代码完成:

df.cumsum(axis=1) / (df != 0).cumsum(axis=1)

结果将会是:

       2001  2002      2003      2004      2005  2006
Name1   2.0   3.5  3.500000  3.500000  3.666667  4.25
Name2   1.0   2.5  2.333333  2.333333  2.750000  2.75
Name3   NaN   5.0  5.000000  5.000000  5.000000  3.50

1
正如楼主所说,没有3.66(也没有2.333和其他值)。他想要的“累积”函数非常奇怪,不幸的是,你提供的解决方案并不是他想要的。 - Fabrizio

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