データの長いテーブル(約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
_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
_
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-reduction
をsum-reduction
とscaling-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
df.set_index(np.arange(len(df)) // 2).mean(level=0)
pd.rolling()
を使用してこの問題にアプローチし、ローリング平均を作成してから、iloc
を使用して1秒ごとの要素を取得することができます。
df = df.rolling(2).mean()
df = df.iloc[::2, :]
最初の観測が欠落することに注意してください(つまり、ローリングは上部から始まります)。