@@ -5957,13 +5957,21 @@ def polyfit(
59575957 The coefficients of the best fit for each variable in this dataset.
59585958 [var]_polyfit_residuals
59595959 The residuals of the least-square computation for each variable (only included if `full=True`)
5960+ When the matrix rank is deficient, np.nan is returned.
59605961 [dim]_matrix_rank
59615962 The effective rank of the scaled Vandermonde coefficient matrix (only included if `full=True`)
5963+ The rank is computed ignoring the NaN values that might be skipped.
59625964 [dim]_singular_values
59635965 The singular values of the scaled Vandermonde coefficient matrix (only included if `full=True`)
59645966 [var]_polyfit_covariance
59655967 The covariance matrix of the polynomial coefficient estimates (only included if `full=False` and `cov=True`)
59665968
5969+ Warns
5970+ -----
5971+ RankWarning
5972+ The rank of the coefficient matrix in the least-squares fit is deficient.
5973+ The warning is not raised with in-memory (not dask) data and `full=True`.
5974+
59675975 See also
59685976 --------
59695977 numpy.polyfit
@@ -5997,10 +6005,6 @@ def polyfit(
59976005 degree_dim = utils .get_temp_dimname (self .dims , "degree" )
59986006
59996007 rank = np .linalg .matrix_rank (lhs )
6000- if rank != order and not full :
6001- warnings .warn (
6002- "Polyfit may be poorly conditioned" , np .RankWarning , stacklevel = 4
6003- )
60046008
60056009 if full :
60066010 rank = xr .DataArray (rank , name = xname + "matrix_rank" )
@@ -6009,7 +6013,7 @@ def polyfit(
60096013 sing = xr .DataArray (
60106014 sing ,
60116015 dims = (degree_dim ,),
6012- coords = {degree_dim : np .arange (order )[:: - 1 ] },
6016+ coords = {degree_dim : np .arange (rank - 1 , - 1 , - 1 ) },
60136017 name = xname + "singular_values" ,
60146018 )
60156019 variables [sing .name ] = sing
@@ -6018,11 +6022,14 @@ def polyfit(
60186022 if dim not in da .dims :
60196023 continue
60206024
6021- if skipna is None :
6022- if isinstance (da .data , dask_array_type ):
6023- skipna_da = True
6024- else :
6025- skipna_da = np .any (da .isnull ())
6025+ if isinstance (da .data , dask_array_type ) and (
6026+ rank != order or full or skipna is None
6027+ ):
6028+ # Current algorithm with dask and skipna=False neither supports
6029+ # deficient ranks nor does it output the "full" info (issue dask/dask#6516)
6030+ skipna_da = True
6031+ elif skipna is None :
6032+ skipna_da = np .any (da .isnull ())
60266033
60276034 dims_to_stack = [dimname for dimname in da .dims if dimname != dim ]
60286035 stacked_coords : Dict [Hashable , DataArray ] = {}
@@ -6040,9 +6047,15 @@ def polyfit(
60406047 if w is not None :
60416048 rhs *= w [:, np .newaxis ]
60426049
6043- coeffs , residuals = duck_array_ops .least_squares (
6044- lhs , rhs .data , rcond = rcond , skipna = skipna_da
6045- )
6050+ with warnings .catch_warnings ():
6051+ if full : # Copy np.polyfit behavior
6052+ warnings .simplefilter ("ignore" , np .RankWarning )
6053+ else : # Raise only once per variable
6054+ warnings .simplefilter ("once" , np .RankWarning )
6055+
6056+ coeffs , residuals = duck_array_ops .least_squares (
6057+ lhs , rhs .data , rcond = rcond , skipna = skipna_da
6058+ )
60466059
60476060 if isinstance (name , str ):
60486061 name = "{}_" .format (name )
0 commit comments