diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 4aee6f72b1d53..e2e8ddcc47271 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -33,8 +33,6 @@ Other enhancements - - .. _whatsnew_0200.api_breaking: Backwards incompatible API changes @@ -82,3 +80,5 @@ Performance Improvements Bug Fixes ~~~~~~~~~ +`read_stata` can now handle some format 111 files, which are produced +by SAS when generating Stata dta files (:issue:11526, :issue:14159) diff --git a/pandas/io/stata.py b/pandas/io/stata.py index 25f13048a73fd..985ea9c051505 100644 --- a/pandas/io/stata.py +++ b/pandas/io/stata.py @@ -34,8 +34,8 @@ from pandas.tslib import NaT, Timestamp _version_error = ("Version of given Stata file is not 104, 105, 108, " - "113 (Stata 8/9), 114 (Stata 10/11), 115 (Stata 12), " - "117 (Stata 13), or 118 (Stata 14)") + "111 (Stata 7SE), 113 (Stata 8/9), 114 (Stata 10/11), " + "115 (Stata 12), 117 (Stata 13), or 118 (Stata 14)") _statafile_processing_params1 = """\ convert_dates : boolean, defaults to True @@ -1183,7 +1183,7 @@ def _get_seek_variable_labels(self): def _read_old_header(self, first_char): self.format_version = struct.unpack('b', first_char)[0] - if self.format_version not in [104, 105, 108, 113, 114, 115]: + if self.format_version not in [104, 105, 108, 111, 113, 114, 115]: raise ValueError(_version_error) self.byteorder = struct.unpack('b', self.path_or_buf.read(1))[ 0] == 0x1 and '>' or '<' diff --git a/pandas/io/tests/data/stata7_111.dta b/pandas/io/tests/data/stata7_111.dta new file mode 100644 index 0000000000000..e87fa3a72ff8e Binary files /dev/null and b/pandas/io/tests/data/stata7_111.dta differ diff --git a/pandas/io/tests/test_stata.py b/pandas/io/tests/test_stata.py index 7752fff5247c0..1849b32a4a7c8 100644 --- a/pandas/io/tests/test_stata.py +++ b/pandas/io/tests/test_stata.py @@ -82,6 +82,8 @@ def setUp(self): self.dta22_118 = os.path.join(self.dirpath, 'stata14_118.dta') self.dta23 = os.path.join(self.dirpath, 'stata15.dta') + self.dta24_111 = os.path.join(self.dirpath, 'stata7_111.dta') + def read_dta(self, file): # Legacy default reader configuration return read_stata(file, convert_dates=True) @@ -1219,6 +1221,20 @@ def test_repeated_column_labels(self): read_stata(self.dta23, convert_categoricals=True) tm.assertTrue('wolof' in cm.exception) + def test_stata_111(self): + # 111 is an old version but still used by current versions of + # SAS when exporting to Stata format. We do not know of any + # on-line documentation for this version. + df = read_stata(self.dta24_111) + original = pd.DataFrame({'y': [1, 1, 1, 1, 1, 0, 0, np.NaN, 0, 0], + 'x': [1, 2, 1, 3, np.NaN, 4, 3, 5, 1, 6], + 'w': [2, np.NaN, 5, 2, 4, 4, 3, 1, 2, 3], + 'z': ['a', 'b', 'c', 'd', 'e', '', 'g', 'h', + 'i', 'j']}) + original = original[['y', 'x', 'w', 'z']] + tm.assert_frame_equal(original, df) + + if __name__ == '__main__': nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], exit=False)