def lowess(endog, exog, frac=(2.0 / 3), it=3):
 x = exog
 if (exog.ndim != 1):
  raise ValueError('exog must be a vector')
 if (endog.ndim != 1):
  raise ValueError('endog must be a vector')
 if (endog.shape[0] != x.shape[0]):
  raise ValueError('exog and endog must have same length')
 n = exog.shape[0]
 fitted = np.zeros(n)
 k = int((frac * n))
 index_array = np.argsort(exog)
 x_copy = np.array(exog[index_array])
 y_copy = endog[index_array]
 (fitted, weights) = _lowess_initial_fit(x_copy, y_copy, k, n)
 for i in range(it):
  _lowess_robustify_fit(x_copy, y_copy, fitted, weights, k, n)
 out = np.array([x_copy, fitted]).T
 out.shape = (n, 2)
 return out

def lowess ( endog , exog , frac = ( 2.0 / 3 ) , it = 3 ) : x = exog if ( exog . ndim != 1 ) : raise ValueError ( 'exog must be a vector' ) if ( endog . ndim != 1 ) : raise ValueError ( 'endog must be a vector' ) if ( endog . shape [ 0 ] != x . shape [ 0 ] ) : raise ValueError ( 'exog and endog must have same length' ) n = exog . shape [ 0 ] fitted = np . zeros ( n ) k = int ( ( frac * n ) ) index_array = np . argsort ( exog ) x_copy = np . array ( exog [ index_array ] ) y_copy = endog [ index_array ] ( fitted , weights ) = _lowess_initial_fit ( x_copy , y_copy , k , n ) for i in range ( it ) : _lowess_robustify_fit ( x_copy , y_copy , fitted , weights , k , n ) out = np . array ( [ x_copy , fitted ] ) . T out . shape = ( n , 2 ) return out
returns y-values estimated using the lowess function in statsmodels .