Announcement

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

  • Using levelsof to generate values for use in foreach loop

    I'm using Stata15.1 on a Mac.

    I would like to generate graphs of prices over time by manufacturer, for a lot of different variations on a product, which are described in the string variable doseform.

    the data look like this:

    Code:
    * Example generated by -dataex-. To install: ssc install dataex
    clear
    input float(mf quarter) str9 doseform float price
    1 223 "1.25_coat" 1985.1534
    1 206 "1.25_coat" 1674.6786
    1 218 "1.25_coat" 1984.0492
    1 217 "1.25_coat"  1724.997
    1 209 "1.25_coat"   1724.63
    1 216 "1.25_coat" 1725.0236
    1 208 "1.25_coat"  1724.879
    1 219 "1.25_coat"  1985.959
    1 214 "1.25_coat" 1725.2493
    1 212 "1.25_coat" 1724.4856
    1 211 "1.25_coat"  1724.994
    1 210 "1.25_coat" 1725.9756
    2 220 "1.25_coat" 1985.5067
    2 222 "1.25_coat"  1984.586
    2 221 "1.25_coat"  1984.821
    2 205 "1.25_coat" 1675.8374
    2 215 "1.25_coat"  1726.285
    2 207 "1.25_coat" 1674.7893
    2 213 "1.25_coat"  1725.028
    2 204 "1.25_coat" 1675.1063
    2 210 "1000_coat"         .
    2 217 "1000_coat"         .
    2 207 "1000_coat"  1471.778
    1 222 "1000_coat"      1230
    1 218 "1000_coat"    1571.4
    1 205 "1000_coat"    1591.8
    1 219 "1000_coat"         .
    1 209 "1000_coat"    1509.7
    1 215 "1000_coat"         .
    1 206 "1000_coat" 1564.8334
    1 208 "1000_coat"         .
    1 216 "1000_coat"         .
    3 211 "1000_coat"         .
    3 214 "1000_coat"         .
    3 213 "1000_coat"         .
    3 223 "1000_coat"         .
    3 220 "1000_coat"         .
    3 212 "1000_coat"      1851
    3 204 "1000_coat" 1497.4828
    3 221 "1000_coat"         .
    end
    format %tq quarter
    I want to perform various operations, including graphing, separately over the different values of doseform.

    Following the advice in method 2 here: https://www.stata.com/support/faqs/d...-with-foreach/, I decided to use levelsof to generate values (levels) over which to loop foreach, then the user-generated bytwoway ado to make the graphs. My code looks like this:

    Code:
    levelsof doseform, local(levels)
    foreach l of local levels {
    bytwoway line price quarter if doseform == `l', by(manufacturer)
    }
    This gives me the following output:


    . levelsof doseform, local(levels)
    `"1.25_coat"' `"1000_coat"' `"15_coat"' `"1_coat"' `"2.5_coat"' `"2_coat"' `"4_c
    > oat"' `"500_coat"' `"500_tab"' `"50_coat"' `"5_coat"' `"750_tab"' `"850_coat"'
    > `"850_tab"' `"_coat"'

    . foreach l of local levels {
    2. bytwoway line price quarter if doseform == `l', by(mf)
    3. }
    1.25_coat invalid name


    But if I simply use that "invalid name" in the command directly:

    Code:
    bytwoway line price quarter if doseform  == "1.25_coat", by(mf)
    I get the graph I want.
    I have tried using the 'clean' option with levelsof in case it was an issue with "", but it also did not work.

    Thanks for any help you can provide.



  • #2
    The issue arises because you need quotation marks around the reference to `l' inside your loop. The quotation marks you see around each level in the -levelsof- output are not passed through to your commands in side the loop when you reference `l'. When you write -... if doseform == `l'-, Stata expands that as -...if doseform == 1.25_coat-, and then rightly complains that 1.25_coat is not a valid variable name.

    Code:
    levelsof doseform, local(levels)
    foreach l of local levels {
        twoway line price quarter if doseform == `"`l'"', by(manufacturer)
    }
    will resolve that problem.

    (I have replaced your -bytwoway- with -twoway-. I'm not aware of any -bytwoway- command: certainly it is not part of official Stata, and I'm not familiar with any such user-written command. If you really have a -bytwoway- command, please explain where it comes from.)

    Finally, I will just note that with that problem solved, you will still have a difficulty: your code does not save the graphs after they are created, so each iteration through the loop will overwrite the previous contents of the Graph window. At the end, you will be left with only the graph of results for doseform == "_coat". You should either store the graphs in memory with the -name()- option, or -save- or -export- the graphs inside the loop.

    Comment


    • #3
      Thanks. That works well, including adding the export command to the loop.

      The bytwoway is a user-generated ado, contributed by Matthieu Gomez. https://github.com/matthieugomez/byt...ster/README.md
      It differs from twoway because it automatically puts the subcategories (in this case manufactuer) on the same graph, while twoway, as in your example above, puts them on different graphs. If there is another tidy way to do this which avoids having to type out separate line commands for 12 or 13 different manufacturers, but which also allows me easily to edit options such as title and legend size, I'd be very keen to know about it.

      Bests, ep

      Comment


      • #4
        Search the forum for
        mentions of “linkplot” e.g. my post of 19 Feb 2019.

        Comment

        Working...
        X