Skip to content

Commit 64ab8f3

Browse files
committed
Allow _FillValue and missing_value to differ (Fixes pydata#1749)
The CF standard permits both values, and them to have different values, so we should not be treating this as an error--just mask out all of them.
1 parent 8e4231a commit 64ab8f3

File tree

2 files changed

+20
-20
lines changed

2 files changed

+20
-20
lines changed

xarray/coding/variables.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import numpy as np
88
import pandas as pd
99

10-
from ..core import dtypes, duck_array_ops, indexing, utils
10+
from ..core import dtypes, duck_array_ops, indexing
1111
from ..core.pycompat import dask_array_type
1212
from ..core.variable import Variable
1313

@@ -152,26 +152,22 @@ def encode(self, variable, name=None):
152152
def decode(self, variable, name=None):
153153
dims, data, attrs, encoding = unpack_for_decoding(variable)
154154

155+
raw_fill_values = []
155156
if 'missing_value' in attrs:
156-
# missing_value is deprecated, but we still want to support it as
157-
# an alias for _FillValue.
158-
if ('_FillValue' in attrs and
159-
not utils.equivalent(attrs['_FillValue'],
160-
attrs['missing_value'])):
161-
raise ValueError("Conflicting _FillValue and missing_value "
162-
"attrs on a variable {!r}: {} vs. {}\n\n"
163-
"Consider opening the offending dataset "
164-
"using decode_cf=False, correcting the "
165-
"attrs and decoding explicitly using "
166-
"xarray.decode_cf()."
167-
.format(name, attrs['_FillValue'],
168-
attrs['missing_value']))
169-
attrs['_FillValue'] = attrs.pop('missing_value')
157+
missing = pop_to(attrs, encoding, 'missing_value', name=name)
158+
# Need to handle single and multiple values in 'missing_value'
159+
try:
160+
raw_fill_values.extend(missing)
161+
except TypeError:
162+
raw_fill_values.append(missing)
170163

171164
if '_FillValue' in attrs:
172-
raw_fill_value = pop_to(attrs, encoding, '_FillValue', name=name)
165+
raw_fill_values.append(pop_to(attrs, encoding, '_FillValue',
166+
name=name))
167+
168+
if raw_fill_values:
173169
encoded_fill_values = [
174-
fv for fv in np.ravel(raw_fill_value) if not pd.isnull(fv)]
170+
fv for fv in np.ravel(raw_fill_values) if not pd.isnull(fv)]
175171

176172
if len(encoded_fill_values) > 1:
177173
warnings.warn("variable {!r} has multiple fill values {}, "

xarray/tests/test_conventions.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,16 @@ def test(self):
156156

157157

158158
def test_decode_cf_with_conflicting_fill_missing_value():
159-
var = Variable(['t'], np.arange(10),
159+
expected = Variable(['t'], [np.nan, np.nan, 2], {'units': 'foobar'})
160+
expected[[0, 1]] = np.nan
161+
var = Variable(['t'], np.arange(3),
160162
{'units': 'foobar',
161163
'missing_value': 0,
162164
'_FillValue': 1})
163-
with raises_regex(ValueError, "_FillValue and missing_value"):
164-
conventions.decode_cf_variable('t', var)
165+
with warnings.catch_warnings(record=True) as w:
166+
actual = conventions.decode_cf_variable('t', var)
167+
assert_identical(actual, expected)
168+
assert 'has multiple fill' in str(w[0].message)
165169

166170
expected = Variable(['t'], np.arange(10), {'units': 'foobar'})
167171

0 commit comments

Comments
 (0)