Announcement

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

  • Error in foreach loop with mata

    Hi all

    My goal is to calculate an index using mata for multiple data files (200+ cities) in the working directory, "d:/cities". I have to use mata because some matrix operations are fast for my analysis. I calculate an index using mata, and save it to a temp file. The following code works for the one data file (one city):


    ************************************************** ************************************************** *****
    clear all
    infile str4 cityname jobs latitude longitude using "d:/cities/nyc.txt", clear

    drop if jobs==0

    mata:
    jobs = st_data(.,"jobs")
    n = length(jobs)
    d = J(n,n,.) // Initiate the pair-wise distance matrix
    for (i=1;i<=n;i++) {
    for (j=1;j<=n;j++) {
    d[i,j]=exp(-sqrt((longitude [i]-longitude [j])^2+(latitude [i]-latitude [j])^2))
    }
    }
    index = cross(cross(jobs,d)',jobs)/sum(jobs)/sum(jobs)
    st_numscalar("myindex", index)
    end

    local myindex=index
    tempname memhold
    postfile `memhold' str4 cityname myindex using "d:\cities\output\index_out.dta", replace
    post `memhold' (cityname[1]) (`myindex')
    postclose `memhold'
    ************************************************** ************************************************** *****

    But if I use a foreach loop to repeat the above calculation for many cities, the code does not go through, but stops with an error message, -- break --

    ************************************************** ************************************************** *****
    clear all
    cd "d:/cities"
    fs *.txt // Get the list of the file names
    foreach f in `r(files)' {
    infile str4 cityname jobs latitude longitude using "d:/cities/`f'", clear

    mata:
    jobs = st_data(.,"jobs")
    n = length(jobs)
    d = J(n,n,.) // Initiate the pair-wise distance matrix
    for (i=1;i<=n;i++) {
    for (j=1;j<=n;j++) {
    d[i,j]=exp(-sqrt((longitude [i]-longitude [j])^2+(latitude [i]-latitude [j])^2))
    }
    }
    index = cross(cross(jobs,d)',jobs)/sum(jobs)/sum(jobs) // This index is a scalar.
    st_numscalar("myindex", index)
    end

    local myindex=index
    tempname memhold
    postfile `memhold' str4 cityname myindex using "d:\cities\output\index_out.dta", replace
    post `memhold' (cityname[1]) (`myindex')
    }
    postclose `memhold'
    ************************************************** ************************************************** *****

    I expected `myindex' values are stored in the "d:\cities\output\index_out.dta" for each city, but the program does not run. I would really appreciate it if someone could provide some help to tackle the problem.

    Sincerely,

    Bill K.



  • #2
    You get the error because an end statement is interpreted as a break when encountered within a loop. The following illustrates the issue

    Code:
    foreach n in 1 2 {
        dis `n'
        end
    }
    Note that the display statement never executes. The solution has been pointed out by Maarten Buis on Statalist before:

    http://www.stata.com/statalist/archi.../msg00393.html

    Comment


    • #3
      I prefer Maarten's solution of writing a specific mata function for the task, so mata code lies in a different place and makes the do-file more readable. But if you want to avoid this solution you can use semi-colons as delimiters in your mata code. Note the use of the brackets to delimit the mata part. Here is an example

      Code:
      forval i = 1/2 {
        mata {
       
        for (i=1;i<=2;i++) {;
      printf("i=%2.0f\n",i);
      }; } }

      Comment


      • #4
        To Robert: Thanks for the link. I could get around my problem by creating a separate ado file.

        To Christophe: Thanks for the tip. Maarten's solution looks elegant, but I equally like your solution. Yours worked nice for my project.

        Comment


        • #5
          Hi @Christophe Kolodziejczyk, I'm trying your solution with 2 statements in the Mata function but it does not work properly. It gives a message "code follows on the same line as close brace". Following is my code. Could you please help me to have a look?

          Code:
          forval n = 1/5{
              mata{
              
              for (n = 1; n<=5 ; n++){ ;
              b_M`n' = b_M`n'B5 - b_M`n'B1 ;
              z_M`n' = b_M`n'/(((se_M`n'B1^2/)+(se_M`n'B5^2/))^(1/2)) ;
              };
          }
          }
          I would greatly appreciate your help!

          Comment

          Working...
          X