web-dev-qa-db-ja.com

テーブル内のすべてのx行の平均を計算し、新しいテーブルを作成します

データの長いテーブル(約200行x 50列)があり、2行ごとおよびテーブルの各列の平均値を計算できるコードを作成する必要があります。最終出力は平均の新しいテーブルです。値。これは明らかにExcelで実行するのがおかしいです!私はpython3を使用しており、同様の質問をいくつか認識しています: ここここ および ここ 。しかし、複数の列を処理して整理されたデータテーブルを作成するには、エレガントなコードが必要なので、これらはどれも役に立ちません。ちなみに、私の元のデータテーブルはpandasを使用してインポートされ、データフレームとして定義されていますが、パンダでこれを行う簡単な方法を見つけることができませんでした。ヘルプに感謝します。

テーブルの例(ショートバージョン)は次のとおりです。

a   b   c   d
2   50  25  26
4   11  38  44
6   33  16  25
8   37  27  25
10  28  48  32
12  47  35  45
14  8   16  7
16  12  16  30
18  22  39  29
20  9   15  47

予想される平均表:

a    b     c     d
3   30.5  31.5  35
7   35    21.5  25
11  37.5  41.5  38.5
15  10    16    18.5
19  15.5  27    38
20
Gnu

_df.index//2_を使用して人工的なグループを作成し(または@DSMが指摘したように、np.arange(len(df))//2を使用して-すべてのインデックスで機能するように)、次にgroupbyを使用できます。

_df.groupby(np.arange(len(df))//2).mean()
Out[13]: 
      a     b     c     d
0   3.0  30.5  31.5  35.0
1   7.0  35.0  21.5  25.0
2  11.0  37.5  41.5  38.5
3  15.0  10.0  16.0  18.5
4  19.0  15.5  27.0  38.0
_
21
ayhan

NumPythonicの方法は、df.valuesで要素をNumPy配列として抽出し、次に3Dに沿って2要素とaxis=1に沿って4要素でaxis=2配列に再形成し、axis=1に沿って平均削減を実行し、最後にデータフレームに変換することです。

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

結局のところ、NumPyの非常に効率的なツールを導入することができます: np.einsum これをaverage-reductionsum-reductionscaling-downの組み合わせとして実行するには、次のようにします-

pd.DataFrame(np.einsum('ijk->ik',df.values.reshape(-1,2,df.shape[1]))/2.0)

提案されたアプローチは、行数が2で割り切れると仮定していることに注意してください。

また、 noted by @DSM のように、列名を保持するには、Dataframeに戻すときにcolumns=df.columnsを追加する必要があります。つまり、

pd.DataFrame(...,columns=df.columns)

サンプルの実行-

>>> df
    0   1   2   3
0   2  50  25  26
1   4  11  38  44
2   6  33  16  25
3   8  37  27  25
4  10  28  48  32
5  12  47  35  45
6  14   8  16   7
7  16  12  16  30
8  18  22  39  29
9  20   9  15  47
>>> pd.DataFrame(df.values.reshape(-1,2,df.shape[1]).mean(1))
    0     1     2     3
0   3  30.5  31.5  35.0
1   7  35.0  21.5  25.0
2  11  37.5  41.5  38.5
3  15  10.0  16.0  18.5
4  19  15.5  27.0  38.0
>>> pd.DataFrame(np.einsum('ijk->ik',df.values.reshape(-1,2,df.shape[1]))/2.0)
    0     1     2     3
0   3  30.5  31.5  35.0
1   7  35.0  21.5  25.0
2  11  37.5  41.5  38.5
3  15  10.0  16.0  18.5
4  19  15.5  27.0  38.0

ランタイムテスト-

このセクションでは、 @ayhan's solution with groupby を含む、パフォーマンスの問題を解決するためにこれまでにリストされた3つのアプローチすべてをテストしてみましょう。

In [24]: A = np.random.randint(0,9,(200,50))

In [25]: df = pd.DataFrame(A)

In [26]: %timeit df.groupby(df.index//2).mean() # @ayhan's solution
1000 loops, best of 3: 1.61 ms per loop

In [27]: %timeit pd.DataFrame(df.values.reshape(-1,2,df.shape[1]).mean(1))
1000 loops, best of 3: 317 µs per loop

In [28]: %timeit pd.DataFrame(np.einsum('ijk->ik',df.values.reshape(-1,2,df.shape[1]))/2.0)
1000 loops, best of 3: 266 µs per loop
6
Divakar
df.set_index(np.arange(len(df)) // 2).mean(level=0)
4
piRSquared

pd.rolling()を使用してこの問題にアプローチし、ローリング平均を作成してから、ilocを使用して1秒ごとの要素を取得することができます。

df = df.rolling(2).mean() 
df = df.iloc[::2, :]

最初の観測が欠落することに注意してください(つまり、ローリングは上部から始まります)。

2
seeiespi