user191919
user191919

Reputation: 754

Bimonthly Time Standard in Stata

Stata does not seem to have a bimonthly (twice a month) time standard. I have time series at this rather uncommon frequency. I was wondering what would be the best way to circumvent this in Stata. Does anybody have a suggestion? Would creating an artificial time index be the easiest way to go?

Upvotes: 0

Views: 632

Answers (3)

Nick Cox
Nick Cox

Reputation: 37208

This answer hinges entirely on a late comment by the OP that

I have a regularity, but it's of the sort every 3rd and 19th day of month

Let's take that literally. The spirit of such dates is that they are approximately equally spaced, and useful as such, but for many time series problems, we will want to pretend that they are exactly equally spaced. No existing date type in Stata corresponds, but it is easy to create one.

The first block of code just creates a sandbox example dataset, given that the OP did not provide one.

clear 
set obs 48 
egen m = seq(), from(1) to(12) block(2) 
egen y = seq(), from(2015) to(2016) block(24) 
gen dailydate = mdy(m, cond(mod(_n, 2), 3, 19), y) 
format dailydate %td 
list

     +-----------------------+
     |  m      y   dailydate |
     |-----------------------|
  1. |  1   2015   03jan2015 |
  2. |  1   2015   19jan2015 |
  3. |  2   2015   03feb2015 |
  4. |  2   2015   19feb2015 |
  5. |  3   2015   03mar2015 |
     |-----------------------|
  6. |  3   2015   19mar2015 |
  7. |  4   2015   03apr2015 |
  8. |  4   2015   19apr2015 |
  9. |  5   2015   03may2015 |
 10. |  5   2015   19may2015 |
     |-----------------------|
 11. |  6   2015   03jun2015 |
 12. |  6   2015   19jun2015 |
 13. |  7   2015   03jul2015 |
 14. |  7   2015   19jul2015 |
 15. |  8   2015   03aug2015 |
     |-----------------------|
 16. |  8   2015   19aug2015 |
 17. |  9   2015   03sep2015 |
 18. |  9   2015   19sep2015 |
 19. | 10   2015   03oct2015 |
 20. | 10   2015   19oct2015 |
     |-----------------------|
 21. | 11   2015   03nov2015 |
 22. | 11   2015   19nov2015 |
 23. | 12   2015   03dec2015 |
 24. | 12   2015   19dec2015 |
 25. |  1   2016   03jan2016 |
     |-----------------------|
 26. |  1   2016   19jan2016 |
 27. |  2   2016   03feb2016 |
 28. |  2   2016   19feb2016 |
 29. |  3   2016   03mar2016 |
 30. |  3   2016   19mar2016 |
     |-----------------------|
 31. |  4   2016   03apr2016 |
 32. |  4   2016   19apr2016 |
 33. |  5   2016   03may2016 |
 34. |  5   2016   19may2016 |
 35. |  6   2016   03jun2016 |
     |-----------------------|
 36. |  6   2016   19jun2016 |
 37. |  7   2016   03jul2016 |
 38. |  7   2016   19jul2016 |
 39. |  8   2016   03aug2016 |
 40. |  8   2016   19aug2016 |
     |-----------------------|
 41. |  9   2016   03sep2016 |
 42. |  9   2016   19sep2016 |
 43. | 10   2016   03oct2016 |
 44. | 10   2016   19oct2016 |
 45. | 11   2016   03nov2016 |
     |-----------------------|
 46. | 11   2016   19nov2016 |
 47. | 12   2016   03dec2016 |
 48. | 12   2016   19dec2016 |
     +-----------------------+

Code here is based on the assumption that there should be precisely 24 values in each year. However, the code allows for the possibility that dates are repeated because the data are panel data; and it allows gaps to exist whereby some dates are not present in the dataset.

We first extract month, day and year components of the daily dates. These variables may already exist (one of many details the OP is not making clear).

gen month = month(dailydate) 
gen year = year(dailydate) 
gen day = day(dailydate) 
assert inlist(day, 3, 19) 

Then a bimonthly date in the spirit of Stata's dates has origin at the start of 1960. This detail is not important, but it is not difficult either. Users can't specify new display formats, but what we can do is assign value labels to the new dates which correspond to display formats of the original daily dates. Here labmask must be installed before it can be used: search labmask gives download locations.

gen newdate = 24 * (year - 1960) + 2 * (month - 1) + (day == 19) 
list, sepby(year month) 

     +------------------------------------------------------+
     |  m      y   dailydate   month   year   day   newdate |
     |------------------------------------------------------|
  1. |  1   2015   03jan2015       1   2015     3      1320 |
  2. |  1   2015   19jan2015       1   2015    19      1321 |
     |------------------------------------------------------|
  3. |  2   2015   03feb2015       2   2015     3      1322 |
  4. |  2   2015   19feb2015       2   2015    19      1323 |
     |------------------------------------------------------|
  5. |  3   2015   03mar2015       3   2015     3      1324 |
  6. |  3   2015   19mar2015       3   2015    19      1325 |
     |------------------------------------------------------|
  7. |  4   2015   03apr2015       4   2015     3      1326 |
  8. |  4   2015   19apr2015       4   2015    19      1327 |
     |------------------------------------------------------|
  9. |  5   2015   03may2015       5   2015     3      1328 |
 10. |  5   2015   19may2015       5   2015    19      1329 |
     |------------------------------------------------------|
 11. |  6   2015   03jun2015       6   2015     3      1330 |
 12. |  6   2015   19jun2015       6   2015    19      1331 |
     |------------------------------------------------------|
 13. |  7   2015   03jul2015       7   2015     3      1332 |
 14. |  7   2015   19jul2015       7   2015    19      1333 |
     |------------------------------------------------------|
 15. |  8   2015   03aug2015       8   2015     3      1334 |
 16. |  8   2015   19aug2015       8   2015    19      1335 |
     |------------------------------------------------------|
 17. |  9   2015   03sep2015       9   2015     3      1336 |
 18. |  9   2015   19sep2015       9   2015    19      1337 |
     |------------------------------------------------------|
 19. | 10   2015   03oct2015      10   2015     3      1338 |
 20. | 10   2015   19oct2015      10   2015    19      1339 |
     |------------------------------------------------------|
 21. | 11   2015   03nov2015      11   2015     3      1340 |
 22. | 11   2015   19nov2015      11   2015    19      1341 |
     |------------------------------------------------------|
 23. | 12   2015   03dec2015      12   2015     3      1342 |
 24. | 12   2015   19dec2015      12   2015    19      1343 |
     |------------------------------------------------------|
 25. |  1   2016   03jan2016       1   2016     3      1344 |
 26. |  1   2016   19jan2016       1   2016    19      1345 |
     |------------------------------------------------------|
 27. |  2   2016   03feb2016       2   2016     3      1346 |
 28. |  2   2016   19feb2016       2   2016    19      1347 |
     |------------------------------------------------------|
 29. |  3   2016   03mar2016       3   2016     3      1348 |
 30. |  3   2016   19mar2016       3   2016    19      1349 |
     |------------------------------------------------------|
 31. |  4   2016   03apr2016       4   2016     3      1350 |
 32. |  4   2016   19apr2016       4   2016    19      1351 |
     |------------------------------------------------------|
 33. |  5   2016   03may2016       5   2016     3      1352 |
 34. |  5   2016   19may2016       5   2016    19      1353 |
     |------------------------------------------------------|
 35. |  6   2016   03jun2016       6   2016     3      1354 |
 36. |  6   2016   19jun2016       6   2016    19      1355 |
     |------------------------------------------------------|
 37. |  7   2016   03jul2016       7   2016     3      1356 |
 38. |  7   2016   19jul2016       7   2016    19      1357 |
     |------------------------------------------------------|
 39. |  8   2016   03aug2016       8   2016     3      1358 |
 40. |  8   2016   19aug2016       8   2016    19      1359 |
     |------------------------------------------------------|
 41. |  9   2016   03sep2016       9   2016     3      1360 |
 42. |  9   2016   19sep2016       9   2016    19      1361 |
     |------------------------------------------------------|
 43. | 10   2016   03oct2016      10   2016     3      1362 |
 44. | 10   2016   19oct2016      10   2016    19      1363 |
     |------------------------------------------------------|
 45. | 11   2016   03nov2016      11   2016     3      1364 |
 46. | 11   2016   19nov2016      11   2016    19      1365 |
     |------------------------------------------------------|
 47. | 12   2016   03dec2016      12   2016     3      1366 |
 48. | 12   2016   19dec2016      12   2016    19      1367 |
     +------------------------------------------------------+

gen sdate = string(dailydate, "%tdd_m_CY") 
labmask newdate, values(sdate) 

The result of that last block is not shown here, but the resulting value labels are like 3 Jan 2015: you can assign any other date display format you like.

Upvotes: 1

dimitriy
dimitriy

Reputation: 9460

In my experience, bimonthly is not always well defined.

If the gap is always regular, say every other Friday (dow=5), you can use the delta() option like this:

clear
set obs 1488
gen date = (_n-1)*14
tsset date, delta(14)
gen lag_of_date = L1.date
gen two_lags_of_date = L2.date
format *date %td
gen dow=dow(date)
list in -10/L, clean noobs

This is yields:

. list in -11/L, clean noobs

         date   lag_of_~e   two_lag~e   dow  
    12aug2016   29jul2016   15jul2016     5  
    26aug2016   12aug2016   29jul2016     5  
    09sep2016   26aug2016   12aug2016     5  
    23sep2016   09sep2016   26aug2016     5  
    07oct2016   23sep2016   09sep2016     5  
    21oct2016   07oct2016   23sep2016     5  
    04nov2016   21oct2016   07oct2016     5  
    18nov2016   04nov2016   21oct2016     5  
    02dec2016   18nov2016   04nov2016     5  
    16dec2016   02dec2016   18nov2016     5  
    30dec2016   16dec2016   02dec2016     5  

As you can see, the lag operators all work as expected and give you the Friday's date from two and four weeks prior, and not the previous Thursday and Wednesday or missings.

If the pattern is not regular because of holidays or whatnot, then take a look at the business calendar functionality. Using your constraint from the comments, that would look something like this:

set more off

/* (1) Make a business calendar file */ 

/* (1a) Make a header with date range and the date that zero corresponds to (MODIFY THIS!) */
capture file close bc
file open bc using my_biz_cal.stbcal, write replace
file write bc "version 14.1" _n
file write bc `"purpose "3rd and 19th of every month""' _n
file write bc "range 03jan2000 19dec2025" _n
file write bc "centerdate 03jan2016" _n

/* (1b) Drop all the non-3rd and non-19th dates based on folk wisdom with a loop:   
Thirty days has September,
April, June, and November.
All the rest have thirty-one,
Except for February alone,
Which hath but twenty-eight days clear,
And twenty-nine in each leap year.
*/

foreach mon in `=lower("`c(Mons)'")' {

    if inlist("`mon'","sep","apr","jun","nov")==1 {
        foreach d in 1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 21 22 23 24 25 26 27 28 29 30 {
            file write bc "omit date `d'`mon'*" _n
        }
    }

    else if inlist("`mon'","feb")==1 {
        foreach d in 1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 21 22 23 24 25 26 27 28 29 {
            file write bc  "omit date `d'`mon'*" _n
        }

    }

    else {
        foreach d in 1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 21 22 23 24 25 26 27 28 29 30 31 {
            file write bc "omit date `d'`mon'*" _n
        }

    }
}

file close bc

/* (2) Try Using The Business Calendar */
clear
bcal load my_biz_cal
set obs 100
gen my_date = _n-50
format my_date %tbmy_biz_cal
tsset my_date
gen lag_of_date = L1.my_date
gen two_lags_of_date = L2.my_date
format *date %tbmy_biz_cal
list in 1/10, clean noobs
di %tbmy_biz_cal -1
di %tbmy_biz_cal 0
di %tbmy_biz_cal 1

Upvotes: 1

ℕʘʘḆḽḘ
ℕʘʘḆḽḘ

Reputation: 19375

yes that's the only solution

create your time index and then

tsset my_time_index

Upvotes: 0

Related Questions