2016-11-21 4 views
2

У меня есть dataframe так:Как вычислить среднее из n последовательных столбцов?

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 

, который я хотел бы преобразовать в dataframe который выглядит следующим образом:

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

Таким образом, A_G1 является mean колонн A_1 и A_2, A_G2 - mean колонн A_3 и A_4; то же самое относится к B_G1 и B_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 

Есть ли лучший способ сделать это т.е. векторизованным способом?

ответ

4

Это может работать для вас:

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 

Но я не тестировал против вашего «прямой» реализации.

+0

Работает отлично, спасибо! Напротив, теперь он может принять его позже, если ничего лучше не появится. – Cleb

+0

@Cleb Просто понял, что в этом случае вам тоже не нужна «dropna». –

+0

Быстрый вопрос: предположим, что есть также 'A_5' и' A_6' и 'B_5' и' B_6'; как нужно изменить команду? Изменение 'окна' до 3 и использование' 1 :: 3' не сработало. – Cleb

2

Вот на основе NumPy Векторизованных решение с использованием reshaping -

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

Sample пробегов -

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 
+0

Отлично работает, спасибо также за скорость сравнение (upvoted)! – Cleb

Смежные вопросы