Pandas:计算 Z 分数以避免 "look ahead" 偏差
Pandas: Calculating a Z-score to avoid "look ahead" bias
我在名为 "df" 的数据框中有时间序列数据,我计算 z-score 的代码如下:
mean = df.mean()
standard_dev = df.std()
z_score = (df - mean) / standard_dev
我想使用各自的观察结果和记录观察点时已知的数据来计算每个观察结果的 z 分数。即我不想使用标准偏差,意思是合并特定时间点之后发生的数据。我只想使用时间 t, t-1, t-2....
的数据
我该怎么做?
您可以分配两个新列,其中包含先前项目的均值和标准差。我在这里假设,您的时间序列数据在 'time_series_data':
列中
len_ = len(df)
df['mean_past'] = [np.mean(df['time_series_data'][0:lv+1]) for lv in range(len_)]
df['std_past'] = [np.std(df['time_series_data'][0:lv+1]) for lv in range(len_)]
df['z_score'] = (df['time_series_data'] - df['mean_past']) / df['std_past']
编辑:如果你想对所有列进行 z 评分,你可以定义一个函数,计算 z 评分并将其应用于数据框的所有列:
def z_score_column(column):
len_ = len(column)
mean = [np.mean(column[0:lv+1]) for lv in range(0,len_)]
std = [np.std(column[0:lv+1]) for lv in range(0,len_)]
return [(c-m)/s for c,m,s in zip(column, mean, std)]
df = pd.DataFrame(np.random.rand(10,5))
df.apply(z_score_column)
使用 .expanding()
- col
作为您要为其计算统计信息的列(如果您希望为整个数据框计算统计信息,请删除 [col]
):
您可能需要先按时间列对值进行排序 - 表示为 time_col
(以防尚未排序):
df=df.sort_values("time_col", axis=0)
然后:
df[col].sub(df[col].expanding().mean()).div(df[col].expanding().std())
参考:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.expanding.html
示例数据:
import pandas as pd
df=pd.DataFrame({"a": list("xyzpqrstuv"), "b": [6,5,7,1,-9,0,3,5,2,8]})
df["c"]=df["b"].sub(df["b"].expanding().mean()).div(df["b"].expanding().std())
输出:
a b c
0 x 6 NaN
1 y 5 -0.707107
2 z 7 1.000000
3 p 1 -1.425880
4 q -9 -1.677484
5 r 0 -0.281450
6 s 3 0.210502
7 t 5 0.534207
8 u 2 -0.046142
9 v 8 1.062430
我在名为 "df" 的数据框中有时间序列数据,我计算 z-score 的代码如下:
mean = df.mean()
standard_dev = df.std()
z_score = (df - mean) / standard_dev
我想使用各自的观察结果和记录观察点时已知的数据来计算每个观察结果的 z 分数。即我不想使用标准偏差,意思是合并特定时间点之后发生的数据。我只想使用时间 t, t-1, t-2....
的数据我该怎么做?
您可以分配两个新列,其中包含先前项目的均值和标准差。我在这里假设,您的时间序列数据在 'time_series_data':
列中len_ = len(df)
df['mean_past'] = [np.mean(df['time_series_data'][0:lv+1]) for lv in range(len_)]
df['std_past'] = [np.std(df['time_series_data'][0:lv+1]) for lv in range(len_)]
df['z_score'] = (df['time_series_data'] - df['mean_past']) / df['std_past']
编辑:如果你想对所有列进行 z 评分,你可以定义一个函数,计算 z 评分并将其应用于数据框的所有列:
def z_score_column(column):
len_ = len(column)
mean = [np.mean(column[0:lv+1]) for lv in range(0,len_)]
std = [np.std(column[0:lv+1]) for lv in range(0,len_)]
return [(c-m)/s for c,m,s in zip(column, mean, std)]
df = pd.DataFrame(np.random.rand(10,5))
df.apply(z_score_column)
使用 .expanding()
- col
作为您要为其计算统计信息的列(如果您希望为整个数据框计算统计信息,请删除 [col]
):
您可能需要先按时间列对值进行排序 - 表示为 time_col
(以防尚未排序):
df=df.sort_values("time_col", axis=0)
然后:
df[col].sub(df[col].expanding().mean()).div(df[col].expanding().std())
参考: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.expanding.html
示例数据:
import pandas as pd
df=pd.DataFrame({"a": list("xyzpqrstuv"), "b": [6,5,7,1,-9,0,3,5,2,8]})
df["c"]=df["b"].sub(df["b"].expanding().mean()).div(df["b"].expanding().std())
输出:
a b c
0 x 6 NaN
1 y 5 -0.707107
2 z 7 1.000000
3 p 1 -1.425880
4 q -9 -1.677484
5 r 0 -0.281450
6 s 3 0.210502
7 t 5 0.534207
8 u 2 -0.046142
9 v 8 1.062430