我试图找到一种方法来迭代代码,在很多列上进行线性回归,直到Z3。这是一个名为df1
的数据帧片段 Time A1 A2 A3 B1 B2 B3
1 1.00 6.64 6.82 6.79 6.70 6.95 7.02
2 2.00 6.70 6.86 6.92 NaN NaN NaN
3 3.00 NaN NaN NaN 7.07 7.27 7.40
4 4.00 7.15 7.26 7.26 7.19 NaN NaN
5 5.00 NaN NaN NaN NaN 7.40 7.51
6 5.50 7.44 7.63 7.58 7.54 NaN NaN
7 6.00 7.62 7.86 7.71 NaN NaN NaN
此代码仅返回非常一列的线性回归的斜率系数,并将该值连接到一个名为series的numpy系列,以下是提取第一列斜率的样子:
from sklearn.linear_model import LinearRegression
series = np.array([]) #blank list to append result
df2 = df1[~np.isnan(df1['A1'])] #removes NaN values for each column to apply sklearn function
df3 = df2[['Time','A1']]
npMatrix = np.matrix(df3)
X, Y = npMatrix[:,0], npMatrix[:,1]
slope = LinearRegression().fit(X,Y) # either this or the next line
m = slope.coef_[0]
series= np.concatenate((SGR_trips, m), axis = 0)
现在,我正在使用这段代码,取代" A1"使用新的列名一直到" Z3"这是非常低效的。我知道有一些简单的方法可以用一些模块来做到这一点,但我的缺点是在时间序列中具有所有这些中间NaN值,所以看起来我只限于这种方法,或类似的东西。
我尝试使用for循环,例如:
for col in df1.columns:
并替换' A1',例如使用代码中的col,但这似乎不起作用。
有什么方法可以更有效地做到这一点吗?
谢谢!
答案 0 :(得分:6)
time = df[['Time']]
pd.DataFrame(np.linalg.pinv(time.T.dot(time)).dot(time.T).dot(df.fillna(0)),
['Slope'], df.columns)
使用封闭形式的OLS
在这种情况下,X
为time
,我们将time
定义为df[['Time']]
。我使用双括号来保留数据帧及其两个维度。如果我做了单括号,我会得到一个系列及其一个维度。那么点积不是很漂亮。
是np.linalg.pinv(time.T.dot(time)).dot(time.T)
Y
是df.fillna(0)
。是的,我们可以一次完成一个专栏,但为什么我们可以完全这样做。你必须处理NaN
。你会怎么想象与他们打交道?只有在你有数据的时候才这样做?这相当于在NaN
点放置零。所以,我做到了。
最后,我使用pd.DataFrame(stuff, ['Slope'], df.columns)
包含原始标签在一个地方的所有斜坡。
注意我计算了时间对自身的回归斜率。为什么不?它就在那里。它的值是1.0。大!我可能做对了!
答案 1 :(得分:1)
对于适度数量(例如,少于数千)的列,循环是一个不错的策略。如果没有看到您的实施,我就无法说出错误,但这是我的版本,有效:
slopes = []
for c in cols:
if c=="Time": break
mask = ~np.isnan(df1[c])
x = np.atleast_2d(df1.Time[mask].values).T
y = np.atleast_2d(df1[c][mask].values).T
reg = LinearRegression().fit(x, y)
slopes.append(reg.coef_[0])
我已经简化了一些代码,以避免创建这么多临时DataFrame
个对象,但它也应该可以正常工作。