在pandas中使用groupby循环多个变量组合
我有一些数据,比如:
df = pandas.DataFrame({"X1":[1,2,5]*4, "X2":[1,2,10]*4,
"Y":[2,4,6]*4, "group":["A","B"]*6})
我想为每个组和每个相关变量组合创建一个线性回归斜率系数的表格,类似于:
group x y coef
A X1 Y 0.97
A X2 Y 0.85
B X1 Y 0.73
B X2 Y 0.81
我试着这样做:
def OLS_slope_coef(df, xcol=0, ycol=1):
x = df.ix[:,xcol]
y = df.ix[:,ycol]
slope, intercept, r, p, stderr = scipy.stats.linregress(x, y)
return(slope)
s_df = pandas.DataFrame()
for x in ['X1', 'X2']:
for y in ['Y']:
s_df.ix[(x, y), 'coef'] = df.groupby('group').apply(OLS_slope_coef, x, y)
但是出现了一个错误:ValueError: Incompatible indexer with Series
。
有没有什么办法可以做到这一点?我不在乎group
、x
和y
这些变量是索引还是数据框的列(反正我会用.reset_index()
来重置索引)。
1 个回答
0
问题在于,.apply
返回的是一个包含两个元素的序列(因为有两个组),这两个元素的索引分别是 'A' 和 'B',所以这和 .ix[(x,y), 'coef']
不兼容。你可以选择这样做:
s_df = pd.DataFrame(index=['A', 'B'])
for x in ['X1', 'X2']:
for y in ['Y']:
s_df.loc[:, x + '-coef'] = df.groupby('group').apply(OLS_slope_coef, x, y)
这样会得到:
X1-coef X2-coef
A 0.92 0.37
B 0.92 0.37
[2 rows x 2 columns]
或者,在被应用的函数内部进行循环,并返回一个数据框:
import pandas as pd
def ols(df, xcols):
from itertools import chain
from scipy.stats import linregress
fitcols = ['slope', 'intercept', 'rval', 'pval', 'stderr']
cols = pd.MultiIndex.from_tuples([(var, k) for var in xcols for k in fitcols])
fit = [linregress(df[xcol], df.Y) for xcol in xcols]
return pd.DataFrame([list(chain(*fit))], columns=cols)
fit = df.groupby('group').apply(ols, xcols=['X1', 'X2'])
fit.reset_index(level=1, drop=True, inplace=True)
这样会得到:
X1 X2
slope intercept rval pval stderr slope intercept rval pval stderr
group
A 0.92 1.54 0.96 0 0.13 0.37 2.4 0.91 0.01 0.08
B 0.92 1.54 0.96 0 0.13 0.37 2.4 0.91 0.01 0.08
[2 rows x 10 columns]