2017-07-11 5 views
0

私はDataFrameにある時系列データの拡張Zスコアを計算したいが、複数の列の平均と標準偏差を使ってデータを標準化したいが、別々に各列内の平均および標準偏差ではなく、私はgroupbyとDataFrame.expandingの組み合わせを使いたいと思っていますが、私はそれを理解できないようです。ここではいくつかのサンプルデータです:複数の列にわたるZスコアを拡大する

import pandas as pd 
import numpy as np 
np.random.seed(42) 

df = pd.DataFrame(np.random.rand(5,5), 
        columns=list('ABCDE'), 
        index=pd.date_range('2016-12-31', periods=5)) 

df.index.name = 'DATE' 

df 

入力:

enter image description here

所望の出力:

enter image description here

私が持っている行と個々の列などのデータ系列ダウン日付。私が望むのは、拡張Zスコアを計算した同じ形の新しいDataFrameです。私が何をするかわからないのは、df.expanding(2).mean()メソッドを複数の列に集約させることです。つまり、列Aの拡大平均を取って列Aの値から差し引くのではなく、列AからEの値の拡大平均をとり、その平均値をAの値から差し引きたい。

Excelで考えると、=AVERAGE(B$2:B3)=AVERAGE($B$2:$F3)の違いが私の話です。前者を行うには信じられないほど単純ですが(df.expanding(2).mean())、私は私の人生のために後者をする方法を理解できません。

groupby,stack()expanding()のようなさまざまな組み合わせを試したことがあります。

答えて

0

これは、すべての列をプールする拡張Zスコアを計算しようとする私自身の試みです。それをより効率的に行う方法についてのコメントは歓迎されます。

def pooled_expanding_zscore(df, min_periods=2): 
"""Calculates an expanding Z-Score down the rows of the DataFrame while pooling all of the columns. 

Assumes that indexes are not hierarchical. 
Assumes that df does not have columns named 'exp_mean' and 'exp_std'. 
""" 

# Get last sorted column name 
colNames = df.columns.values 
colNames.sort() 
lastCol = colNames[-1] 

# Index name 
indexName = df.index.name 

# Normalize DataFrame 
df_stacked = pd.melt(df.reset_index(),id_vars=indexName).sort_values(by=[indexName,'variable']) 

# Calculates the expanding mean and standard deviation on df_stacked 
# Keeps just the rows where 'variable'==lastCol 
df_exp = df_stacked.expanding(2)['value'] 
df_stacked.loc[:,'exp_mean'] = df_exp.mean() 
df_stacked.loc[:,'exp_std'] = df_exp.std() 

exp_stats = (df_stacked.loc[df_stacked.variable==lastCol,:] 
      .reset_index() 
      .drop(['index','variable','value'], axis=1) 
      .set_index(indexName)) 

# add exp_mean and exp_std back to df 
df = pd.concat([df,exp_stats],axis=1) 

# Calculate Z-Score 
df_mat = df.loc[:,colNames].as_matrix() 
exp_mean_mat = df.loc[:,'exp_mean'].as_matrix()[:,np.newaxis] 
exp_std_mat = df.loc[:,'exp_std'].as_matrix()[:,np.newaxis] 
zScores = pd.DataFrame(
    (df_mat - exp_mean_mat)/exp_std_mat, 
    index=df.index, 
    columns=colNames) 

# Use min_periods to kill off early rows 
zScores.iloc[:min_periods-1,:] = np.nan 

return zScores 
関連する問題