Pandas' 在多列上使用应用函数进行扩展
Pandas' expanding with apply function on multiple columns
是否可以使用熊猫的扩展函数来计算使用 window 对象的多个列的多项式回归的系数?
我有一个包含两列的数据框,一个预测变量和一个响应列。我想使用 pandas' expanding() 函数来计算每个扩展系列对的二阶多项式回归的相应系数。对于每一行,我想从应用于所有先前行的回归中获取更新的系数。
import pandas as pd
import numpy as np
def func1(df):
# some processing
return np.polyfit(df['Input'], df['Response'], 2)
def func2(x, y):
# some processing
return np.polyfit(x, y, 2)
np.random.seed(0)
df = pd.DataFrame(np.random.rand(10, 2).round(2),
columns=['Input', 'Response'])
df[['Coef1', 'Coef2', 'Coef3']] = df.expanding(min_periods=3).apply(func)
我希望输出如下所示:
>>> df
Input Response Coef1 Coef2 Coef3
0 0.63 0.23 NaN NaN NaN
1 0.45 0.11 NaN NaN NaN
2 0.17 0.71 NaN NaN NaN
3 0.17 0.32 0.19 0.54 0.50
4 0.65 0.99 0.48 0.23 0.60
5 0.21 0.54 0.71 0.89 0.97
6 0.63 0.73 0.22 0.05 0.80
7 0.54 0.23 0.87 0.01 0.25
8 0.33 0.06 0.18 0.96 0.03
9 0.18 0.72 0.13 0.38 0.13
我的不同尝试导致了两种类型的错误。如果我使用使用数据帧作为参数的函数,例如 df[['Coef1', 'Coef2', 'Coef3']] = df.expanding(min_periods=3).apply(func1))
,我会得到 KeyError: 'Input'
。
如果我使用第二个函数在 df['Coef1', 'Coef2', 'Coef3'] = df.expanding(min_periods=3).apply(lambda x: func2(x['Input'], x['Output']))
之前提取参数,我会得到
DataError: No numeric types to aggregate
但是,如果我尝试 df.expanding().cov(pairwise=True)
,它表明可以对 expanding
返回的对象的不同列执行计算。
这里有一个类似的问题:。但是,在函数中调用 expanding() 的解决方案似乎不适用于这种情况。
如果有任何指点或建议,我将不胜感激。
我发现 a package 可以用 numpy 做到这一点,所以它启发了我手动完成它:
def func_np(df):
length = len(df)
if length == 1:
return [[0], [0], [0]]
coef1, coef2, coef3 = [], [], []
x = df['A'].to_numpy() # This is the predictor column
y = df['B'].to_numpy() # This is the response column
for step in range(1, length + 1):
weights = np.polyfit(x[: step], y[: step], 2) # 2 is the polynomial's order
coef1.append(weights[0])
coef2.append(weights[1])
coef3.append(weights[2])
# Note that coef1, coef2, coef3 correspond to the polynomial terms from highest to lowest
# It is easier to return a data frame, so that we can reassign the result to the initial one
return pd.DataFrame({'Coef1': coef1, 'Coef2': coef2, 'Coef3': coef3})
我想用 Numba 来加快执行速度,但它不识别 np.polyfit 函数。此外,我还没有找到一种巧妙的方法将结果分配回初始数据框。这就是为什么我仍然对使用 expanding()
看到一个简单且更“pythonic”的解决方案感兴趣
我怀疑您正在寻找的是即将推出的 pandas=1.3
中的新 df.expanding(..., method='table')
(参见 "Other enhancements")。
同时,您可以使用循环“手动”完成(抱歉):
xy = df.values
df['c1 c2 c3'.split()] = np.stack([
func2(*xy[:n].T) if n >= 3 else np.empty(3)*np.nan
for n in range(xy.shape[0])
])
示例:
np.random.seed(0)
df = pd.DataFrame(np.random.rand(10, 2).round(2),
columns=['Input', 'Response'])
# the code above, then
>>> df
Input Response c1 c2 c3
0 0.55 0.72 NaN NaN NaN
1 0.60 0.54 NaN NaN NaN
2 0.42 0.65 NaN NaN NaN
3 0.44 0.89 -22.991453 22.840171 -4.887179
4 0.96 0.38 -29.759096 29.213620 -6.298277
5 0.79 0.53 0.454036 -1.369701 1.272156
6 0.57 0.93 0.122450 -0.874260 1.113586
7 0.07 0.09 -1.010312 0.623331 0.696287
8 0.02 0.83 -2.687387 2.995143 -0.079214
9 0.78 0.87 -1.425030 1.294210 0.442684
是否可以使用熊猫的扩展函数来计算使用 window 对象的多个列的多项式回归的系数?
我有一个包含两列的数据框,一个预测变量和一个响应列。我想使用 pandas' expanding() 函数来计算每个扩展系列对的二阶多项式回归的相应系数。对于每一行,我想从应用于所有先前行的回归中获取更新的系数。
import pandas as pd
import numpy as np
def func1(df):
# some processing
return np.polyfit(df['Input'], df['Response'], 2)
def func2(x, y):
# some processing
return np.polyfit(x, y, 2)
np.random.seed(0)
df = pd.DataFrame(np.random.rand(10, 2).round(2),
columns=['Input', 'Response'])
df[['Coef1', 'Coef2', 'Coef3']] = df.expanding(min_periods=3).apply(func)
我希望输出如下所示:
>>> df
Input Response Coef1 Coef2 Coef3
0 0.63 0.23 NaN NaN NaN
1 0.45 0.11 NaN NaN NaN
2 0.17 0.71 NaN NaN NaN
3 0.17 0.32 0.19 0.54 0.50
4 0.65 0.99 0.48 0.23 0.60
5 0.21 0.54 0.71 0.89 0.97
6 0.63 0.73 0.22 0.05 0.80
7 0.54 0.23 0.87 0.01 0.25
8 0.33 0.06 0.18 0.96 0.03
9 0.18 0.72 0.13 0.38 0.13
我的不同尝试导致了两种类型的错误。如果我使用使用数据帧作为参数的函数,例如 df[['Coef1', 'Coef2', 'Coef3']] = df.expanding(min_periods=3).apply(func1))
,我会得到 KeyError: 'Input'
。
如果我使用第二个函数在 df['Coef1', 'Coef2', 'Coef3'] = df.expanding(min_periods=3).apply(lambda x: func2(x['Input'], x['Output']))
之前提取参数,我会得到
DataError: No numeric types to aggregate
但是,如果我尝试 df.expanding().cov(pairwise=True)
,它表明可以对 expanding
返回的对象的不同列执行计算。
这里有一个类似的问题:
我发现 a package 可以用 numpy 做到这一点,所以它启发了我手动完成它:
def func_np(df):
length = len(df)
if length == 1:
return [[0], [0], [0]]
coef1, coef2, coef3 = [], [], []
x = df['A'].to_numpy() # This is the predictor column
y = df['B'].to_numpy() # This is the response column
for step in range(1, length + 1):
weights = np.polyfit(x[: step], y[: step], 2) # 2 is the polynomial's order
coef1.append(weights[0])
coef2.append(weights[1])
coef3.append(weights[2])
# Note that coef1, coef2, coef3 correspond to the polynomial terms from highest to lowest
# It is easier to return a data frame, so that we can reassign the result to the initial one
return pd.DataFrame({'Coef1': coef1, 'Coef2': coef2, 'Coef3': coef3})
我想用 Numba 来加快执行速度,但它不识别 np.polyfit 函数。此外,我还没有找到一种巧妙的方法将结果分配回初始数据框。这就是为什么我仍然对使用 expanding()
看到一个简单且更“pythonic”的解决方案感兴趣我怀疑您正在寻找的是即将推出的 pandas=1.3
中的新 df.expanding(..., method='table')
(参见 "Other enhancements")。
同时,您可以使用循环“手动”完成(抱歉):
xy = df.values
df['c1 c2 c3'.split()] = np.stack([
func2(*xy[:n].T) if n >= 3 else np.empty(3)*np.nan
for n in range(xy.shape[0])
])
示例:
np.random.seed(0)
df = pd.DataFrame(np.random.rand(10, 2).round(2),
columns=['Input', 'Response'])
# the code above, then
>>> df
Input Response c1 c2 c3
0 0.55 0.72 NaN NaN NaN
1 0.60 0.54 NaN NaN NaN
2 0.42 0.65 NaN NaN NaN
3 0.44 0.89 -22.991453 22.840171 -4.887179
4 0.96 0.38 -29.759096 29.213620 -6.298277
5 0.79 0.53 0.454036 -1.369701 1.272156
6 0.57 0.93 0.122450 -0.874260 1.113586
7 0.07 0.09 -1.010312 0.623331 0.696287
8 0.02 0.83 -2.687387 2.995143 -0.079214
9 0.78 0.87 -1.425030 1.294210 0.442684