Autorecode: Add value labels indicating the source values. 20100906040502/pspp
authorJohn Darrington <john@darrington.wattle.id.au>
Sun, 5 Sep 2010 12:16:58 +0000 (14:16 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Sun, 5 Sep 2010 12:16:58 +0000 (14:16 +0200)
Autorecode now creates value labels on the new variable to
indicate from which values the new values originate.
Fixes bug #30943

src/language/stats/autorecode.c
tests/language/stats/autorecode.at

index 68571cb2ef4d8f96265824c5c9968f47662f7977..03de84e28592b3d5422df5192518d27b3e01d498 100644 (file)
@@ -28,6 +28,7 @@
 #include "language/lexer/lexer.h"
 #include "language/lexer/variable-parser.h"
 #include "libpspp/array.h"
+#include "libpspp/i18n.h"
 #include "libpspp/compiler.h"
 #include "libpspp/hash-functions.h"
 #include "libpspp/hmap.h"
@@ -36,6 +37,7 @@
 #include "libpspp/str.h"
 
 #include "gl/xalloc.h"
+#include "gl/vasnprintf.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -85,6 +87,7 @@ int
 cmd_autorecode (struct lexer *lexer, struct dataset *ds)
 {
   struct autorecode_pgm *arc = NULL;
+  struct dictionary *dict = dataset_dict (ds);
 
   const struct variable **src_vars = NULL;
   char **dst_names = NULL;
@@ -103,7 +106,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
   /* Parse variable lists. */
   lex_match_id (lexer, "VARIABLES");
   lex_match (lexer, '=');
-  if (!parse_variables_const (lexer, dataset_dict (ds), &src_vars, &n_srcs,
+  if (!parse_variables_const (lexer, dict, &src_vars, &n_srcs,
                               PV_NO_DUPLICATE))
     goto error;
   if (!lex_force_match_id (lexer, "INTO"))
@@ -123,7 +126,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
     {
       const char *name = dst_names[i];
 
-      if (dict_lookup_var (dataset_dict (ds), name) != NULL)
+      if (dict_lookup_var (dict, name) != NULL)
         {
           msg (SE, _("Target variable %s duplicates existing variable %s."),
                name, name);
@@ -190,7 +193,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
       size_t j;
 
       /* Create destination variable. */
-      spec->dst = dict_create_var_assert (dataset_dict (ds), dst_names[i], 0);
+      spec->dst = dict_create_var_assert (dict, dst_names[i], 0);
 
       /* Create array of pointers to items. */
       n_items = hmap_count (&spec->items);
@@ -206,7 +209,40 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
 
       /* Assign recoded values in sorted order. */
       for (j = 0; j < n_items; j++)
-        items[j]->to = direction == ASCENDING ? j + 1 : n_items - j;
+       {
+         const union value *from = &items[j]->from;
+         size_t len;
+         char *recoded_value  = NULL;
+         char *c;
+
+         union value to_val;
+         value_init (&to_val, 0);
+
+         items[j]->to = direction == ASCENDING ? j + 1 : n_items - j;
+         
+         to_val.f = items[j]->to;
+
+         /* Add value labels to the destination variable which indicate
+            the source value from whence the new value comes. */
+
+         if (src_width > 0)
+           recoded_value = 
+             recode_string (UTF8, dict_get_encoding (dict), (char *) value_str (from, src_width), src_width);
+         else
+           recoded_value = asnprintf (NULL, &len, "%g", from->f);
+         
+         /* Remove trailing whitespace */
+         for (c = recoded_value; *c != '\0'; c++)
+           if ( *c == ' ')
+             {
+               *c = '\0';
+               break;
+             }
+
+         var_add_value_label (spec->dst, &to_val, recoded_value);
+         value_destroy (&to_val, 0);
+         free (recoded_value);
+       }
 
       /* Free array. */
       free (items);
index b4e9d41f95ad628bb0c5e22e2ae99e8e4f71717e..6f112def33c1427f175366e63cf443371c78eb3c 100644 (file)
@@ -53,3 +53,57 @@ asdfk,0,3.00,4.00,.00,1.00
 asdfk,1,3.00,3.00,.00,1.00
 ])
 AT_CLEANUP
+
+
+
+AT_SETUP([AUTORECODE long strings and check the value labels])
+AT_DATA([ar.sps],
+  [data list notable list /s (a16) x *.
+begin data.
+widgets      1
+thingummies  2
+oojars       3
+widgets      4
+oojars       5
+thingummies  6
+oojimiflips  7
+end data.
+
+autorecode s into new.
+
+list.
+
+display dictionary.
+])
+
+AT_CHECK([pspp -O format=csv ar.sps], [0],
+  [Table: Data List
+s,x,new
+widgets         ,1.00,4.00
+thingummies     ,2.00,3.00
+oojars          ,3.00,1.00
+widgets         ,4.00,4.00
+oojars          ,5.00,1.00
+thingummies     ,6.00,3.00
+oojimiflips     ,7.00,2.00
+
+Variable,Description,,Position
+s,Format: A16,,1
+,Measure: Nominal,,
+,Display Alignment: Left,,
+,Display Width: 16,,
+x,Format: F8.2,,2
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+new,Format: F8.2,,3
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+,1,oojars,
+,2,oojimiflips,
+,3,thingummies,
+,4,widgets,
+])
+
+AT_CLEANUP