Att,我想在python DataFrame中从lambda函数的多个返回值创建多个列。
与我的演示代码的最后一行类似。
有没有办法实现这个目标?
y = np.random.rand(2,5)
df = pd.DataFrame(y, columns = ["y1", "y2", "y3", "y4", "y5"])
print(df)
def f_polyfit(y1, y2, y3, y4, y5, degree):
y = [y1, y2, y3, y4, y5]
x = [1, 2, 3, 4, 5]
coeffs = np.polyfit(x, y, degree)
coeffs = coeffs.tolist()
# constructe the polynomial formula
p = np.poly1d(coeffs)
# fit values, and mean
y_fit = p(x)
y_avg = np.sum(y)/len(y)
ssreg = np.sum((y_fit-y_avg)**2)
sstot = np.sum((y - y_avg)**2)
R2 = ssreg / sstot
return coeffs[0], R2
# df["slope"], df["R2"] = zip(df.apply(lambda x:f_polyfit(x["y1"], x["y2"], x["y3"], x["y4"], x["y5"], degree = 1), axis = 1))
答案 0 :(得分:3)
一种方法是将返回值包装在pd.Series
中,以便分配给新的数据帧列。
g = lambda x: pd.Series(f_polyfit(x.y1, x.y2, x.y3, x.y5, x.y5, degree=1))
df[['slope', 'R2']] = df.apply(g, axis=1)
答案 1 :(得分:0)
解决方案是理解错误消息"解包的值太多。"当Python遇到像:
这样的解包表达式时a,b = x
迭代x并将第一个值分配给a,第二个赋值给b,等等。如果x的长度恰好为2,则该语句将无错误地执行,但如果x有三个元素,它也会引发"许多值要打开包装。"
您的最后一行代码只有在zip()函数生成的迭代器具有两个元素时才有效。显然,事实并非如此。重要的是要意识到问题与lambda或数据帧无关,而是与Python解包的基础知识有关。
答案 2 :(得分:0)
使用pd.Series
的另一种方法是将输出转换为列表。然后,您可以将新列分配为:
df[['slope', 'R2']] = pd.DataFrame(df.apply(lambda x: f_polyfit(x)).tolist(),
index=df.index)