2017-07-31 45 views
0

我想在給定數據框(dfTest,其中包含向量x的值)的所有行上應用基本樣條函數以獲得更大的(dfBigger)包含矢量xnew的所有值(其中包含x)。當使用應用於熊貓數據幀時傳遞值的形狀錯誤

所以我定義了以下變量:

和基本樣條函數:

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大小沒有說明什麼。我看不到什麼是錯的。有關此代碼的任何幫助和/或評論將不勝感激。

回答

3

df.apply(func)嘗試從func返回的值 中構建新的Series或DataFrame。 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)返回一個Series。
  • 如果func返回一個系列,df.apply(func)返回一個DataFrame。
  • 如果func返回一維NumPy數組,該數組只有一個元素,df.apply(func)返回一個DataFrame。 (不是一個十分有用的情況下,...)
  • 如果func返回一維陣列NumPy的,陣列具有相同數量的元素作爲df具有列,df.apply(func)返回一個數據幀。 (有用的,但有限的)

由於func返回6個值,並且要一個數據幀作爲結果, 的解決方案是讓func返回一個系列代替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 
+0

一流的答案,非常感謝。給定numpy數組時,我真的不明白函數的行爲...我會記得在現在遇到大熊貓問題時嘗試轉換爲Series。 – Djiggy