【问题标题】:How to calculate the mean of n consecutive columns?如何计算n个连续列的平均值?
【发布时间】:2016-11-21 16:44:57
【问题描述】:

我有一个这样的数据框:

import pandas as pd

df = pd.DataFrame({'A_1': [1, 2], 'A_2': [3, 4], 'A_3': [5, 6], 'A_4': [7, 8],
                   'B_1': [0, 2], 'B_2': [4, 4], 'B_3': [9, 6], 'B_4': [5, 8]})

   A_1  A_2  A_3  A_4  B_1  B_2  B_3  B_4
0    1    3    5    7    0    4    9    5
1    2    4    6    8    2    4    6    8

我想将其转换为如下所示的数据框:

   A_G1  A_G2  B_G1  B_G2
0     2     6     2     7
1     3     7     3     7

因此,A_G1 是列 A_1A_2meanA_G2 是列 A_3A_4mean;这同样适用于B_G1B_G2。所以我想做的是计算两个连续列的平均值并将结果作为新列添加到数据框中。

一个简单的实现可能如下所示:

res_df = pd.DataFrame()
for i in range(0, len(df.columns), 2):
    temp_df = df[[i, i + 1]].mean(axis=1)
    res_df = pd.concat([res_df, temp_df], axis=1)

这给了我想要的输出(除了列名):

   0  0  0  0
0  2  6  2  7
1  3  7  3  7

有没有更好的方法,即矢量化方式?

【问题讨论】:

    标签: python performance pandas optimization vectorization


    【解决方案1】:

    这可能对你有用:

    In [15]: df.rolling(window=2,axis=1).mean().iloc[:,1::2]
    Out[15]:
       A_2  A_4  B_2  B_4
    0  2.0  6.0  2.0  7.0
    1  3.0  7.0  3.0  7.0
    

    但我没有针对您的“直接”实现对其进行测试。

    【讨论】:

    • 工作正常,谢谢!暂时赞成,如果没有更好的表现,以后可能会接受。
    • @Cleb 刚刚意识到在这种情况下您也不需要dropna
    • 快速提问:假设还有A_5A_6B_5B_6;那么命令需要如何更改?将 window 更改为 3 并使用 1::3 无效。
    • 对不起,我的意思是我想计算A1A3A4A6 的平均值。我该怎么做?
    • @Cleb 没有尝试过,但可能类似于df.rolling(window=3,axis=1).mean().iloc[:,2::3]
    【解决方案2】:

    这是一个基于 NumPy 的矢量化解决方案,使用 reshaping -

    pd.DataFrame(df.values.reshape(-1,df.shape[1]//n,n).mean(2))
    

    示例运行 -

    In [65]: df
    Out[65]: 
       A_1  A_2  A_3  A_4  B_1  B_2  B_3  B_4
    0    1    3    5    7    0    4    9    5
    1    2    4    6    8    2    4    6    8
    
    In [66]: n = 2
    
    In [67]: pd.DataFrame(df.values.reshape(-1,df.shape[1]//n,n).mean(2))
    Out[67]: 
         0    1    2    3
    0  2.0  6.0  2.0  7.0
    1  3.0  7.0  3.0  7.0
    
    In [68]: n = 4
    
    In [69]: pd.DataFrame(df.values.reshape(-1,df.shape[1]//n,n).mean(2))
    Out[69]: 
         0    1
    0  4.0  4.5
    1  5.0  5.0
    

    运行时测试-

    In [71]: df = pd.DataFrame(np.random.randint(0,9,(200,800)))
    
    In [72]: %timeit df.rolling(window=2,axis=1).mean().iloc[:,1::2]
    100 loops, best of 3: 11 ms per loop # @juanpa.arrivillaga's soln
    
    In [73]: n = 2
    
    In [74]: %timeit pd.DataFrame(df.values.reshape(-1,df.shape[1]//n,n).mean(2))
    100 loops, best of 3: 2.6 ms per loop
    

    【讨论】:

    • 效果很好,也感谢速度比较(赞成)!
    猜你喜欢
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    相关资源
    最近更新 更多