dnl PSPP - a program for statistical analysis. dnl Copyright (C) 2017 Free Software Foundation, Inc. dnl dnl This program is free software: you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation, either version 3 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program. If not, see . dnl AT_BANNER([RECODE transformation]) m4_define([RECODE_SAMPLE_DATA], [DATA LIST LIST NOTABLE/x (f1) s (a4) t (a10). MISSING VALUES x(9)/s('xxx'). BEGIN DATA. 0, '', '' 1, a, a 2, ab, ab 3, abc, abc 4, abcd, abcd 5, 123, 123 6, ' 123', ' 123' 7, +1, +1 8, 1x, 1x 9, abcd, abcdefghi , xxx, abcdefghij END DATA. ]) AT_SETUP([RECODE numeric to numeric, without INTO]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA NUMERIC x0 TO x8 (F3). MISSING VALUES x0 to x8 (9). COMPUTE x0=value(x). RECODE x0 (1=9). COMPUTE x1=value(x). RECODE x1 (1=9)(3=8)(5=7). COMPUTE x2=value(x). RECODE x2 (1=8)(2,3,4,5,6,8=9)(9=1). COMPUTE x3=value(x). RECODE x3 (1 THRU 9=10)(MISSING=11). COMPUTE x4=value(x). RECODE x4 (MISSING=11)(1 THRU 9=10). COMPUTE x5=value(x). RECODE x5 (LOWEST THRU 5=1). COMPUTE x6=value(x). RECODE x6 (4 THRU HIGHEST=2). COMPUTE x7=value(x). RECODE x7 (LO THRU HI=3). COMPUTE x8=value(x). RECODE x8 (SYSMIS=4). LIST x x0 TO x8. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List x,x0,x1,x2,x3,x4,x5,x6,x7,x8 0,0,0,0,0,0,1,0,3,0 1,9,9,8,10,10,1,1,3,1 2,2,2,9,10,10,1,2,3,2 3,3,8,9,10,10,1,3,3,3 4,4,4,9,10,10,1,2,3,4 5,5,7,9,10,10,1,2,3,5 6,6,6,9,10,10,6,2,3,6 7,7,7,7,10,10,7,2,3,7 8,8,8,9,10,10,8,2,3,8 9,9,9,1,10,11,9,2,3,9 .,.,.,.,11,11,.,.,.,4 ]) AT_CLEANUP AT_SETUP([RECODE numeric to numeric, with INTO, without COPY]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA NUMERIC ix0 TO ix8 (F3). RECODE x (1=9) INTO ix0. RECODE x (1=9)(3=8)(5=7) INTO ix1. RECODE x (1=8)(2,3,4,5,6,8=9)(9=1) INTO ix2. RECODE x (1 THRU 9=10)(MISSING=11) INTO ix3. RECODE x (MISSING=11)(1 THRU 9=10) INTO ix4. RECODE x (LOWEST THRU 5=1) INTO ix5. RECODE x (4 THRU HIGHEST=2) INTO ix6. RECODE x (LO THRU HI=3) INTO ix7. RECODE x (SYSMIS=4) INTO ix8. LIST x ix0 TO ix8. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List x,ix0,ix1,ix2,ix3,ix4,ix5,ix6,ix7,ix8 0,.,.,.,.,.,1,.,3,. 1,9,9,8,10,10,1,.,3,. 2,.,.,9,10,10,1,.,3,. 3,.,8,9,10,10,1,.,3,. 4,.,.,9,10,10,1,2,3,. 5,.,7,9,10,10,1,2,3,. 6,.,.,9,10,10,.,2,3,. 7,.,.,.,10,10,.,2,3,. 8,.,.,9,10,10,.,2,3,. 9,.,.,1,10,11,.,2,3,. .,.,.,.,11,11,.,.,.,4 ]) AT_CLEANUP AT_SETUP([RECODE numeric to numeric, with INTO, with COPY]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA NUMERIC cx0 TO cx8 (F3). RECODE x (1=9)(ELSE=COPY) INTO cx0. RECODE x (1=9)(3=8)(5=7)(ELSE=COPY) INTO cx1. RECODE x (1=8)(2,3,4,5,6,8=9)(9=1)(ELSE=COPY) INTO cx2. RECODE x (1 THRU 9=10)(MISSING=11)(ELSE=COPY) INTO cx3. RECODE x (MISSING=11)(1 THRU 9=10)(ELSE=COPY) INTO cx4. RECODE x (LOWEST THRU 5=1)(ELSE=COPY) INTO cx5. RECODE x (4 THRU HIGHEST=2)(ELSE=COPY) INTO cx6. RECODE x (LO THRU HI=3)(ELSE=COPY) INTO cx7. RECODE x (SYSMIS=4)(ELSE=COPY) INTO cx8. RECODE x (5=COPY)(ELSE=22) INTO cx9. LIST x cx0 TO cx9. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List x,cx0,cx1,cx2,cx3,cx4,cx5,cx6,cx7,cx8,cx9 0,0,0,0,0,0,1,0,3,0,22.00 1,9,9,8,10,10,1,1,3,1,22.00 2,2,2,9,10,10,1,2,3,2,22.00 3,3,8,9,10,10,1,3,3,3,22.00 4,4,4,9,10,10,1,2,3,4,22.00 5,5,7,9,10,10,1,2,3,5,5.00 6,6,6,9,10,10,6,2,3,6,22.00 7,7,7,7,10,10,7,2,3,7,22.00 8,8,8,9,10,10,8,2,3,8,22.00 9,9,9,1,10,11,9,2,3,9,22.00 .,.,.,.,11,11,.,.,.,4,22.00 ]) AT_CLEANUP AT_SETUP([RECODE string to string, with INTO, without COPY]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA STRING s0 TO s3 (A4)/t0 TO t3 (A10). RECODE s t ('a'='b')('ab'='bc') INTO s0 t0. RECODE s t ('abcd'='xyzw') INTO s1 t1. RECODE s t ('abc'='def')(ELSE='xyz') INTO s2 t2. RECODE t ('a'='b')('abcdefghi'='xyz')('abcdefghij'='jklmnopqr') INTO t3. RECODE s (MISSING='gone') INTO s3. LIST s t s0 TO s3 t0 TO t3. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List s,t,s0,s1,s2,s3,t0,t1,t2,t3 ,,,,xyz,,,,xyz, a,a,b,,xyz,,b,,xyz,b ab,ab,bc,,xyz,,bc,,xyz, abc,abc,,,def,,,,def, abcd,abcd,,xyzw,xyz,,,xyzw,xyz, 123,123,,,xyz,,,,xyz, 123,123,,,xyz,,,,xyz, +1,+1,,,xyz,,,,xyz, 1x,1x,,,xyz,,,,xyz, abcd,abcdefghi,,xyzw,xyz,,,,xyz,xyz xxx,abcdefghij,,,xyz,gone,,,xyz,jklmnopqr ]) AT_CLEANUP AT_SETUP(RECODE string to string, with INTO, with COPY]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA STRING cs0 TO cs2 (A4)/ct0 TO ct3 (A10). RECODE s t ('a'='b')('ab'='bc')(ELSE=COPY) INTO cs0 ct0. RECODE s t ('abcd'='xyzw')(ELSE=COPY) INTO cs1 ct1. RECODE s t ('abc'='def')(ELSE='xyz')(ELSE=COPY) INTO cs2 ct2. RECODE t ('a'='b')('abcdefghi'='xyz')('abcdefghij'='jklmnopqr')(ELSE=COPY) INTO ct3. LIST s t cs0 TO cs2 ct0 TO ct3. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List s,t,cs0,cs1,cs2,ct0,ct1,ct2,ct3 ,,,,xyz,,,xyz, a,a,b,a,xyz,b,a,xyz,b ab,ab,bc,ab,xyz,bc,ab,xyz,ab abc,abc,abc,abc,def,abc,abc,def,abc abcd,abcd,abcd,xyzw,xyz,abcd,xyzw,xyz,abcd 123,123,123,123,xyz,123,123,xyz,123 123,123,123,123,xyz,123,123,xyz,123 +1,+1,+1,+1,xyz,+1,+1,xyz,+1 1x,1x,1x,1x,xyz,1x,1x,xyz,1x abcd,abcdefghi,abcd,xyzw,xyz,abcdefghi,abcdefghi,xyz,xyz xxx,abcdefghij,xxx,xxx,xyz,abcdefghij,abcdefghij,xyz,jklmnopqr ]) AT_CLEANUP AT_SETUP([RECODE string to numeric]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA NUMERIC ns0 TO ns2 (F3)/nt0 TO nt2 (F3). RECODE s t (CONVERT)(' '=0)('abcd'=1) INTO ns0 nt0. RECODE s t (' '=0)(CONVERT)('abcd'=1) INTO ns1 nt1. RECODE s t ('1x'=1)('abcd'=2)(ELSE=3) INTO ns2 nt2. LIST s t ns0 TO ns2 nt0 TO nt2. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List s,t,ns0,ns1,ns2,nt0,nt1,nt2 ,,.,0,3,.,0,3 a,a,.,.,3,.,.,3 ab,ab,.,.,3,.,.,3 abc,abc,.,.,3,.,.,3 abcd,abcd,1,1,2,1,1,2 123,123,123,123,3,123,123,3 123,123,123,123,3,123,123,3 +1,+1,1,1,3,1,1,3 1x,1x,.,.,1,.,.,1 abcd,abcdefghi,1,1,2,.,.,3 xxx,abcdefghij,.,.,3,.,.,3 ]) AT_CLEANUP AT_SETUP([RECODE numeric to string]) AT_DATA([recode.sps], [RECODE_SAMPLE_DATA STRING sx0 TO sx2 (a10). RECODE x (1 THRU 9='abcdefghij') INTO sx0. RECODE x (0,1,3,5,7,MISSING='xxx') INTO sx1. RECODE x (2 THRU 6,SYSMIS='xyz')(ELSE='foobar') INTO sx2. LIST x sx0 TO sx2. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Data List x,sx0,sx1,sx2 0,,xxx,foobar 1,abcdefghij,xxx,foobar 2,abcdefghij,,xyz 3,abcdefghij,xxx,xyz 4,abcdefghij,,xyz 5,abcdefghij,xxx,xyz 6,abcdefghij,,xyz 7,abcdefghij,xxx,foobar 8,abcdefghij,,foobar 9,abcdefghij,xxx,foobar .,,xxx,xyz ]) AT_CLEANUP AT_SETUP([RECODE bug in COPY]) AT_DATA([recode.sps], [DATA LIST LIST /A (A1) B (A1). BEGIN DATA 1 2 2 3 3 4 END DATA. ** Clearly, the else=copy is superfluous here RECODE A ("1"="3") ("3"="1") (ELSE=COPY). EXECUTE. LIST. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Reading free-form data from INLINE. Variable,Format A,A1 B,A1 Table: Data List A,B 3,2 2,3 1,4 ]) AT_CLEANUP AT_SETUP([RECODE bug in COPY with INTO]) AT_DATA([recode.sps], [DATA LIST LIST /A (A1) B (A1). BEGIN DATA 1 2 2 3 3 4 END DATA. STRING A1 (A1). RECODE A ("1"="3") ("3"="1") (ELSE=COPY) INTO a1. EXECUTE. LIST. ]) AT_CHECK([pspp -O format=csv recode.sps], [0], [Table: Reading free-form data from INLINE. Variable,Format A,A1 B,A1 Table: Data List A,B,A1 1,2,3 2,3,2 3,4,1 ]) AT_CLEANUP AT_SETUP([RECODE increased string widths]) AT_DATA([recode.sps],[dnl data list notable list /x (a1) y (a8) z *. begin data. a a 2 a two 2 b three 2 c b 2 end data. recode x y ("a" = "first") . list. ]) AT_CHECK([pspp -O format=csv recode.sps], [1], [dnl recode.sps:9: error: RECODE: At least one target variable is too narrow for the output values. "recode.sps:9.19-9.25: note: RECODE: This recoding output value has width 5. 9 | recode x y (""a"" = ""first"") . | ^~~~~~~" "recode.sps:9.8-9.10: note: RECODE: Target variable x only has width 1. 9 | recode x y (""a"" = ""first"") . | ^~~" Table: Data List x,y,z a,a,2.00 a,two,2.00 b,three,2.00 c,b,2.00 ]) AT_CLEANUP AT_SETUP([RECODE crash on invalid dest variable]) AT_DATA([recode.sps],[dnl DATA LIST LIST NOTABLE/x (f1) s (a4) t (a10). MISSING VALUES x(9)/s('xxx'). BEGIN DATA. 0, '', '' 1, a, a 2, ab, ab 3, abc, abc END DATA. RECODE x (1=9) INTO ". EXECUTE. dnl " ]) AT_CHECK([pspp -O format=csv recode.sps], [1], [ignore]) AT_CLEANUP AT_SETUP([RECODE syntax errors]) AT_DATA([recode.sps], [dnl DATA LIST LIST NOTABLE/n1 to n4 (F8.0) s1 (A1) s2 (A2) s3 (A3) s4 (A4). RECODE **. RECODE n1 **. RECODE n1(**). RECODE s1(**). RECODE s1('x' THRU 'y'). RECODE n1(1=**). RECODE n1(CONVERT). RECODE n1(1=2)(1='x'). RECODE n1(1='x')(1=2). RECODE s1(CONVERT)('1'='1'). RECODE n1(1=2 **). RECODE n1(CONVERT). RECODE s1(CONVERT) INTO n1 n2. RECODE n1(1='1') INTO xyzzy. RECODE n1(1='1'). RECODE s1('1'=1). RECODE n1(1='1') INTO n2. RECODE s1(CONVERT) INTO s2. RECODE n1 TO n4(1='123456') INTO s1 TO s4. ]) AT_CHECK([pspp -O format=csv recode.sps], [1], [dnl "recode.sps:2.8-2.9: error: RECODE: Syntax error expecting variable name. 2 | RECODE **. | ^~" "recode.sps:3.11-3.12: error: RECODE: Syntax error expecting `('. 3 | RECODE n1 **. | ^~" "recode.sps:4.11-4.12: error: RECODE: Syntax error expecting number. 4 | RECODE n1(**). | ^~" "recode.sps:5.11-5.12: error: RECODE: Syntax error expecting string. 5 | RECODE s1(**). | ^~" "recode.sps:6.15-6.18: error: RECODE: THRU is not allowed with string variables. 6 | RECODE s1('x' THRU 'y'). | ^~~~" "recode.sps:7.13-7.14: error: RECODE: Syntax error expecting output value. 7 | RECODE n1(1=**). | ^~" "recode.sps:8.11-8.17: error: RECODE: CONVERT requires string input values. 8 | RECODE n1(CONVERT). | ^~~~~~~" recode.sps:9: error: RECODE: Output values must be all numeric or all string. "recode.sps:9.13: note: RECODE: This output value is numeric. 9 | RECODE n1(1=2)(1='x'). | ^" "recode.sps:9.18-9.20: note: RECODE: This output value is string. 9 | RECODE n1(1=2)(1='x'). | ^~~" recode.sps:10: error: RECODE: Output values must be all numeric or all string. "recode.sps:10.20: note: RECODE: This output value is numeric. 10 | RECODE n1(1='x')(1=2). | ^" "recode.sps:10.13-10.15: note: RECODE: This output value is string. 10 | RECODE n1(1='x')(1=2). | ^~~" recode.sps:11: error: RECODE: Output values must be all numeric or all string. "recode.sps:11.11-11.17: note: RECODE: This output value is numeric. 11 | RECODE s1(CONVERT)('1'='1'). | ^~~~~~~" "recode.sps:11.24-11.26: note: RECODE: This output value is string. 11 | RECODE s1(CONVERT)('1'='1'). | ^~~" "recode.sps:12.15-12.16: error: RECODE: Syntax error expecting `)'. 12 | RECODE n1(1=2 **). | ^~" "recode.sps:13.11-13.17: error: RECODE: CONVERT requires string input values. 13 | RECODE n1(CONVERT). | ^~~~~~~" recode.sps:14: error: RECODE: Source and target variable counts must match. "recode.sps:14.8-14.9: note: RECODE: There is 1 source variable. 14 | RECODE s1(CONVERT) INTO n1 n2. | ^~" "recode.sps:14.25-14.29: note: RECODE: There are 2 target variables. 14 | RECODE s1(CONVERT) INTO n1 n2. | ^~~~~" recode.sps:15: error: RECODE: All string variables specified on INTO must already exist. (Use the STRING command to create a string variable.) "recode.sps:15.23-15.27: note: RECODE: There is no variable named xyzzy. 15 | RECODE n1(1='1') INTO xyzzy. | ^~~~~" "recode.sps:16.10-16.16: error: RECODE: INTO is required with numeric input values and string output values. 16 | RECODE n1(1='1'). | ^~~~~~~" "recode.sps:17.10-17.16: error: RECODE: INTO is required with string input values and numeric output values. 17 | RECODE s1('1'=1). | ^~~~~~~" "recode.sps:18.23-18.24: error: RECODE: Type mismatch: cannot store string data in numeric variable n2. 18 | RECODE n1(1='1') INTO n2. | ^~" "recode.sps:19.25-19.26: error: RECODE: Type mismatch: cannot store numeric data in string variable s2. 19 | RECODE s1(CONVERT) INTO s2. | ^~" recode.sps:20: error: RECODE: At least one target variable is too narrow for the output values. "recode.sps:20.19-20.26: note: RECODE: This recoding output value has width 6. 20 | RECODE n1 TO n4(1='123456') INTO s1 TO s4. | ^~~~~~~~" "recode.sps:20.29-20.41: note: RECODE: Target variable s1 only has width 1. 20 | RECODE n1 TO n4(1='123456') INTO s1 TO s4. | ^~~~~~~~~~~~~" ]) AT_CLEANUP