Skip to main content
 首页 » 编程设计

python之在 pandas 数据框上使用 apply 时传递值的形状错误

2025年05月04日20zhujiabin

我正在尝试在给定数据帧(dfTest,其中包含向量 x 的值)的所有行上应用基本样条函数以获得更大的函数(dfBigger),它将包含向量 xnew(其中包含 x)的所有值.

因此我定义了以下变量:

import pandas as pd 
import numpy as np 
 
x = [0,1,3,5] 
xnew = range(0,6) 
 
np.random.seed(123) 
dfTest = pd.DataFrame(np.random.rand(12).reshape(3,4)) 

和基本样条函数:

def spline(y, x , xnew): 
    from scipy import interpolate 
    model = interpolate.splrep(x,y, s=0.) 
    ynew = interpolate.splev(xnew,model) 
    result = ynew.round(3) 
    return result 

这似乎有效:

spline(dfTest.iloc[0],x,xnew) 
Out[176]: array([ 0.696,  0.286,  0.161,  0.227,  0.388,  0.551]) 

但是当我尝试将它应用于所有行时:

dfBigger = dfTest.apply(lambda row : spline(row, x, xnew), axis = 1) 

我明白了:

ValueError: Shape of passed values is (3, 6), indices imply (3, 4) 

因为 dfBigger 大小没有在任何地方定义,所以我看不出哪里出了问题。任何有关此代码的帮助和/或评论将不胜感激。

请您参考如下方法:

df.apply(func)尝试从值中构建一个新的 Series 或 DataFrame 由 func 返回。 Series 或 DataFrame 的形状取决于 func 返回的值。为了更好地处理 df.apply 的行为, 尝试以下调用:

dfTest.apply(lambda row: 1, axis=1)                       # Series 
dfTest.apply(lambda row: [1], axis=1)                     # Series 
dfTest.apply(lambda row: [1,2], axis=1)                   # Series 
dfTest.apply(lambda row: [1,2,3], axis=1)                 # Series 
dfTest.apply(lambda row: [1,2,3,4], axis=1)               # Series 
dfTest.apply(lambda row: [1,2,3,4,5], axis=1)             # Series 
 
dfTest.apply(lambda row: np.array([1]), axis=1)           # DataFrame 
dfTest.apply(lambda row: np.array([1,2]), axis=1)         # ValueError 
dfTest.apply(lambda row: np.array([1,2,3]), axis=1)       # ValueError 
dfTest.apply(lambda row: np.array([1,2,3,4]), axis=1)     # DataFrame! 
dfTest.apply(lambda row: np.array([1,2,3,4,5]), axis=1)   # ValueError 
 
dfTest.apply(lambda row: pd.Series([1]), axis=1)          # DataFrame 
dfTest.apply(lambda row: pd.Series([1,2]), axis=1)        # DataFrame 
dfTest.apply(lambda row: pd.Series([1,2,3]), axis=1)      # DataFrame 
dfTest.apply(lambda row: pd.Series([1,2,3,4]), axis=1)    # DataFrame 
dfTest.apply(lambda row: pd.Series([1,2,3,4,5]), axis=1)  # DataFrame 

那么我们可以从这些实验中得出什么规律呢?

  • 如果 func 返回标量或列表,则 df.apply(func) 返回一个系列。
  • 如果 func 返回一个 Series,则 df.apply(func) 返回一个 DataFrame。
  • 如果 func 返回一维 NumPy 数组,并且该数组只有一个元素,df.apply(func) 返回一个 DataFrame。 (不是一个非常有用的案例......)
  • 如果 func 返回一维 NumPy 数组,并且该数组的元素数与 df 的列数相同,df .apply(func) 返回一个 DataFrame。 (有用,但有限)

因为 func 返回 6 个值,而你想要一个 DataFrame 作为结果, 解决方案是让 func 返回一个 Series 而不是 NumPy 数组:

def spline(y, x, xnew): 
    ... 
    return pd.Series(result) 

import numpy as np 
import pandas as pd 
from scipy import interpolate 
 
def spline(y, x, xnew): 
    model = interpolate.splrep(x,y, s=0.) 
    ynew = interpolate.splev(xnew,model) 
    result = ynew.round(3) 
    return pd.Series(result) 
 
x = [0,1,3,5] 
xnew = range(0,6) 
np.random.seed(123) 
dfTest = pd.DataFrame(np.random.rand(12).reshape(3,4)) 
# spline(dfTest.iloc[0],x,xnew) 
dfBigger = dfTest.apply(lambda row : spline(row, x, xnew), axis=1) 
print(dfBigger) 

产量

        0      1      2      3      4      5 
 0  0.696  0.286  0.161  0.227  0.388  0.551 
 1  0.719  0.423  0.630  0.981  1.119  0.685 
 2  0.481  0.392  0.333  0.343  0.462  0.729