Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Is there any workaround to -input-ing within a loop ?

    Dear all

    I know that it is not possible to use -input- in a loop because the "end" one must write at the end of it is in conflict with the loop language. I was wondering if there was any other way to input a long list of elements stored in a macro without doing it manually. To give more context, I am trying to fill a mapping table I was given with new variable labels that only appear in specific files.

    Do you know any other trick to -input- new observations other than manually ?

    Thank you all !

  • #2
    Example please. I can't be sure what a long list of elements stored in a macro means here. In any case input is not used for variable labels.

    Comment


    • #3
      I have the same problem as Nick Cox in post #2. If my guess below does not address your need, please show us code that works outside of a loop.
      Code:
      #delim ;
      local animals `"
      dog
      cat
      "guinea pig"
      fish
      "';
      #delim cr
      macro list _animals
      foreach animal of local animals {
          display "`animal'"
      }
      Code:
      . #delim ;
      delimiter now ;
      . local animals `"
      > dog
      > cat
      > "guinea pig"
      > fish
      > "';
      
      . #delim cr
      delimiter now cr
      . macro list _animals
      _animals:        dog cat "guinea pig" fish
      
      . foreach animal of local animals {
        2.     display "`animal'"
        3. }
      dog
      cat
      guinea pig
      fish
      
      .

      Comment


      • #4
        You are right. Apologies for not providing an example, I wasn't near my laptop.

        Nick : I admit the variable label thing was confusing. I wasn't talking about the Stata variable labels, just about observations that denote what my variable labels should be renamed after. I wanted to add observations from this list of labels because some varlabel from my files of interest are missing .

        Code:
        * Example generated by -dataex-. For more info, type help dataex
        clear
        input str20(id varlabel)
        "fruit1" "apple"
        "fruit2" "pear"  
        "fruit3" "banana"
        end
        Suppose my mapping table looks like this (I'm trying to later on replace the observations of varlabel by the id ones using -frlink- and -frget-). However, this mapping table is incomplete, because assume in my dataset_1 I have :

        Code:
        * Example generated by -dataex-. For more info, type help dataex
        clear
        input str20 varlabel
        "pear"    
        "banana"  
        "apple"    
        "orange"  
        "pineapple"
        end
        What I wanted to do was something like this :

        Code:
        // using dataset_1
        levelsof varlabel in 4/l, local(toadd)
        preserve
        use "`output'/mapping_table.dta", clear
        local a = 4
        
        foreach obs of local toadd {
        input fruit`a' `obs'
        end
        local ++a
        }
        
        save, replace
        restore
        
        frame create mapping_table
        frame mapping_table : use "`output'/mapping_table.dta", clear
        frlink m:1 varlabel, frame(mapping_table)
        frget id, from(mapping_table)
        This is just a code I wrote without testing it because I can't access my data now. It gives you the general idea of what I wanted but obviously it's not possible to include input in a loop. I was wondering if there was another way than just writing input fruit4 orange etc. because I have many other """"fruits"""" coming afterwards and I want to avoid writing them
        Last edited by Thomas Brot; 15 Feb 2023, 15:57.

        Comment


        • #5
          I'm not certain I fully understand what you are looking for, but is it this?
          Code:
          * Example generated by -dataex-. For more info, type help dataex
          clear
          input str20(id varlabel)
          "fruit1" "apple"
          "fruit2" "pear"  
          "fruit3" "banana"
          end
          
          local to_add strawberry grape blueberry orange kiwi
          
          count
          local next_up = r(N) + 1
          local how_many: word count `to_add'
          
          set obs `=_N + `how_many''
          
          foreach t of local to_add {
              replace id = `"fruit`next_up' "' in `next_up'
              replace varlabel = `"`t'"' in `next_up'
              local ++next_up
          }

          Comment


          • #6
            Clyde : Apologies for the late reply, it seems that it is indeed what I'm looking for. Do you know what I should be editing in your code to allow for sentences (including spaces) instead of fruit names ? I'm asking this because if I'm not wrong, the definition of a word in Stata is a series of characters that ends with a space, therefore I'm not sure if the macro function "word count" will work. For instance, what if the local to_add was like this :

            Code:
            local to_add `"this is the first expression"' `"this is the second one"'
            Your help on this is very much appreciated.
            Last edited by Thomas Brot; 19 Feb 2023, 15:50.

            Comment


            • #7
              In post #3 I show how to define a local macro containing quoted multi-word elements. You need
              Code:
              local to_add `"  `"this is the first expression"' `"this is the second one"' "'
              When defining a local or global macro, if Stata encounters a double quote (regular or compound) as the first character, it will expect a matching double quote as the final character, and will remove both. The following examples demonstrate various applications of this rule.
              Code:
              . local gnxl a b c
              
              . macro list _gnxl
              _gnxl:          a b c
              
              . local gnxl "a b c"
              
              . macro list _gnxl
              _gnxl:          a b c
              
              . local gnxl a "b two" c
              
              . macro list _gnxl
              _gnxl:          a "b two" c
              
              . local gnxl "a one" b "c three"
              
              . macro list _gnxl
              _gnxl:          a one" b "c three
              
              . local gnxl "a one" b c
              invalid syntax
              r(198);
              
              . local gnxl ""a one" b c"
              
              . macro list _gnxl
              _gnxl:          "a one" b c
              Let me add that if, as in post #3, you need to stretch the list over several lines,
              Code:
              local testlist2 `" "bob sue" ///
                  "bob" ///
                  "sue bob ed" "'
              won't work, a string cannot span several lines. Instead, use the #delimit command, as I did in post #3.
              Code:
              #delimit ;
              local testlist2 `" "bob sue"
                  "bob"
                  "sue bob ed" "';
              #delimit cr
              So to address your most recent question, if we define the local macro to_add correctly Clyde's code runs correctly.
              Code:
              * Example generated by -dataex-. For more info, type help dataex
              clear
              input str20(id varlabel)
              "fruit1" "apple"
              "fruit2" "pear"  
              "fruit3" "banana"
              end
              
              local to_add `" `"this is the first expression"' `"this is the second one"' "'
              
              count
              local next_up = r(N) + 1
              local how_many: word count `to_add'
              
              set obs `=_N + `how_many''
              
              foreach t of local to_add {
                  replace id = `"fruit`next_up'"' in `next_up'
                  replace varlabel = `"`t'"' in `next_up'
                  local ++next_up
              }
              Code:
              . list, clean noobs
              
                      id                       varlabel  
                  fruit1                          apple  
                  fruit2                           pear  
                  fruit3                         banana  
                  fruit4   this is the first expression  
                  fruit5         this is the second one

              Comment


              • #8
                William : Thank you for your answer and for the extensive details on how to write quoted multi-word elements ! If I can ask just one more question that is just a detail in case the problem arises in my future code :

                What if there's an apostrophe in the quoted expression ? As in

                Code:
                local to_add `" `"this is the first expression"' `"I'm using Stata"' "'
                Will Stata consider it as a closing of the previous single quote opening ` ?

                Comment


                • #9
                  To answer this question definitively (because I have been known to treat my knowledge as more definitive than it is) I would copy and paste the code from post 7 into Stata's do-file editor, make the change you suggest, and run the code and see what happens.

                  It seems to me though that your question indicates less-than-thorough familiarity with the details of Stata's compound double quotes, so along with running the experiment I would refer you to the output of
                  Code:
                  help quotes
                  where you will learn about compound double quotes: the character pairs `" (open compound double quotes) and "' (close compound double quotes), which pair only with each other and not with individual apostrophes and double quotes.

                  Comment

                  Working...
                  X