I'm doing a connected twoway plot with x-axis as dates formatted as %th with values 2011h1 to 2017h2. I want to put a vertical line at 2016h2 but nothing I've tried has worked.
xline(2016h2)
xline("2016h2")
xline(date==2016h2)
xline(date=="2016h2")
I'm thinking it might be because I formatted dates with
gen date = yh(year, half)
format date %th
I think this is a MWE:
age1820 date
10.42 2011h1
10.33 2011h2
11.66 2012h1
11.01 2012h2
14.29 2013h1
10.95 2013h2
12.42 2014h1
7.04 2014h2
7.07 2015h1
6.95 2015h2
4 2016h1
8.07 2016h2
5.98 2017h1
3.19 2017h2
graph twoway connected age1820 date, xline(2016h2)
Your example will not really work as written without some additional work. I think in future posts you may want to shoot for a fully working example to maximize the chance that you get a good answer quickly. This is why I made up some fake data below.
Try something like this:
clear
set obs 20
gen date = _n + 100
format date %th
gen age = _n*2
display %th 116
display %th 117
tw connected age date, xline(116 `=th(2018h2)') tline(2019h1)
The crux of the matter is that Stata deals with dates as integers that have a special label attached to them by the format command (but not a value label). For example, 0 corresponds to 1960h1. In other words, you need to either:
tell xline() the number that corresponds to the date you want
use th() to figure out what that number is and force the evaluation inside xline().
use tline(), which is smart enough to understand dates.
I think the third is the best option.
Related
I'm working on a dataset in Stata
The first column is the name of the firm. the second column is the start date of this firm and the third column is the expiration date of this firm. If the expdate is missing, this firm is still in business. I want to create a variable that will record the number of firms at a given time. (preferably to be a monthly variable)
I'm really lost here. Please help!
Next time, try using dataex (ssc install dataex) rather than a screen shot, this is recommended in the Stata tag wiki, and will help others help you!
Here is an example for how to count the number of firms that are alive in each period (I'll use years, but point out where you can switch to month). This example borrows from Nick Cox's Stata journal article on this topic.
First, load the data:
* Example generated by -dataex-. To install: ssc install dataex
clear
input long(firmID dt_start dt_end)
3923155 20080123 99991231
2913168 20070630 99991231
3079566 20000601 20030212
3103920 20020805 20070422
3357723 20041201 20170407
4536020 20120201 20170407
2365954 20070630 20190630
4334271 20110721 20191130
4334338 20110721 20170829
4334431 20110721 20190429
end
Note that my in my example data my dates are not in Stata format, so I'll convert them here:
tostring dt_start, replace
generate startdate=date(dt_start, "YMD")
tostring dt_end, replace
generate enddate=date(dt_end, "YMD")
format startdate enddate
Next make a variable with the time interval you'd like to count within:
generate startyear = year(startdate)
generate endyear = year(enddate)
In my dataset I have missing end dates that begin with '9999' while you have them as '.' I'll set these to the current year, the assumption being that the dataset is current. You'll have to decide whether this is appropriate in your data.
replace endyear = year(date("$S_DATE","DMY")) if endyear == 9999
Next create an observation for the first and last years (or months) that the firm is alive:
expand 2
by firmID, sort: generate year = cond(_n == 1, startyear, endyear)
keep firmID year
duplicates drop // keeps one observation for firms that die in the period they were born
Now expand the dataset to have an observation for every period between the start and end date. For this I use tsfill.
xtset firmID year
tsfill
Now I have one observation per existing firm in each period. All that remains is to count the observations by year:
egen entities = count(firmID), by(year)
drop firmID
duplicates drop
I'm only starting with Stata but went through a lot of available pages already to find answer to this.
Using simple dataset with two variables aa and bb.
aa is formatted as %td
bb is formatted as %8.0g
The graph command I've been using is as follows:
graph twoway tsline bb,
title("Numbers by Day", size(medsmall))
ytitle("Value", size(small))
xtitle("Date", size(small))
ysize(2)
xsize(4)
tlabel(#15, labsize(vsmall), format(%tcD_m_CY))
ylabel(#10, labsize(vsmall))
I am trying to format dates as something else rather than 21jan2016
but whatever I put in the format function I get an error "Invalid Date"
%tcD_m_CY is just an example from Stata forum: I tried double quotes and other things and it all fails..
(I did use tsset first to define date axis.)
Your question lacks a minimal, complete, verifiable example in so far as (1) it lacks data we can read in and (2) several details in your example are irrelevant to your problem. See https://stackoverflow.com/help/mcve
Your example shows an argument fed to the format() suboption of tlabel() (not function) which starts %tc: this insists to Stata that values which have been input as daily dates (and counted as # days with an origin 0 = 1 January 1960) are to be interpreted as date-times (and counted as # milliseconds with origin 0 = 01jan1960 00:00:00).
So, by your instruction, a daily date such as 25 July 2016 (which is held as 20660 given that origin) is to be displayed as if it were a date-time. Such a date-time is just about 2 seconds after the start of 1 January 1960; and the rest of your display format D_m_CY says "just show me day, month and year" and the day, month and year are, as said, 1 January 1960 according to this instruction.
I see nothing invalid in your date format so far as Stata is concerned; the problem is human, that it is not at all what you want. Naturally, I can't explain exactly what was wrong with whatever other code you tried and don't show us.
The fake data and code below illustrate some technique. For daily dates, labelling every day is usually a bad idea with more than about a week's worth of data, as you just don't have enough space; similarly showing the same year again and again is usually unnecessary and a poor use of space. An axis title such as "Date" is superfluous so long as dates are clearly given. These points apply whatever software you are using.
clear
set obs 15
gen aa = daily("30 Jun 2016", "DMY") + _n
format aa %td
mat bb = (12, 14, 10, 8, 6, 8, 9, 11, 13, 15, 17, 19, 21, 23, 25)
gen bb = bb[1, _n]
tsset aa
graph twoway tsline bb, ///
title("Numbers by Day") ytitle("Value") xtitle("") ///
tlabel(#7, format(%tdd_M))
It's your graph, but the bottom line is simple: daily dates will need some kind of %td format, and %tc format is utterly wrong, on a par with confusing cents and millions of dollars as units.
You don't say exactly what you read, but this is well documented: help datetime in Stata and whatever it points to are all you need to study.
Note also http://www.statalist.org/forums/help#spelling
Hi to all and good time of a day!
Here is my case I need to solve I will very gratefull if you can help me.
I have some data set it contains only one variable date format.
Example:
01JAN2016
06JAN2016
15FEB2016
The second data set is days - holidays for a period 5 years.
Example:
01JAN2016
02JAN2016
and etc, all these days are not working days.
The case is I need to count number of working days from date for every observation from first data set till now. It seems that I need to count number of days
"Now date" minus Date(from first data set) and minus number of days from second data set with holidays (count(date) where Date(from first data set)< date < "Now"
You can define your own type of interval to use with SAS funcions intck and intnx. Here's how to do it:
First create a table of weekdays for whichever years you have holidays for, up to present (or a future) year.
Here we'll start by including all weekdays from 2014 to 2016. This is assuming you don't want to count weekend days. If that's not the case, just modify the code so that the condition "weekday(date) in (2:6)" is not applied. You'll get the full 365 days of the year.
data mon_fri;
do date = "01JAN2014"d to "31DEC2016"d;
if weekday(date) in (2:6) then output;
end;
format date date9.;
run;
Then we'll create a table having all those dates we just created, minus the holidays we have in the table Holidays. We'll place the table in a library called myLib, and rename the date column to "Begin" for compliance with SAS custom intervals.
libname myLib "some/place/on/your/drive";
data mylib.workdays(RENAME=(date=Begin));
merge mon_fri (in=weekday)
Holidays (in=holiday);
by date;
if weekday and not holiday then output;
run;
Now we set up a custom interval which we'll simply call "workdays".
options intervalds=(workdays=mylib.workdays);
From there, all you have left to do is something like this:
data dateCalculations;
set mydata;
numOfDays = intck("workdays", theDate, today());
run;
SAS will take care of counting the number of dates (lines in the workdays dataset) separating the startdate (column called theDate) from the enddate (today's date).
Et voilĂ !
This is wonderful and very helpful. I use two different SAS systems (both on remote Unix servers). Setting the intervalds option only seems to work on one of them. I copy/paste the same code and on the other nothing happens - no warning, no error, it simply doesn't work.
Here is how I'm setting it (download the CSV from Yahoo! Finance for the S&P500, daily data, starting January 1950):
PROC IMPORT DATAFILE="sp500_1950_2016.csv"
OUT=sp500_1950_2016
DBMS=DLM
REPLACE;
delimiter=',';
getnames=yes;
RUN;
data trading_days;
set sp500_1950_2016 (keep = date rename=(date=begin));
where year(begin) < 2017;
run;
options intervalds=(TradingDay=trading_days) ;
Then I call it like so to count number of observations I should have from fund inception to Dec 31, 2016 or when the fund closed, whichever is sooner:
data ops2; set operations_master; where ~missing(inception);
if missing(enddate) then enddate = '31dec2016'd;
datadays = INTCK('TradingDay',inception,enddate);run;
proc univariate; var datadays;run;quit;
On system 1, this works just fine. On system 2, I get 0 for the variable datadays. I've already checked to see if there is a sys admin override on setting the intervalds option, and there is not. Is there another reason why this might not work on a given system?
I have a string variable in Stata called YEAR with format "aaaa" (e.g. 2011). I want to replace "aaaa" with "31decaaaa" and destring the obtained variable.
My feeling is that the best way to proceed could be firstly destringing the variable YEAR and then adding "31dec". To destring the variable YEAR I have tried the command date but it does not seem to work. Any suggestion?
It would be best to describe your eventual goal here, as use of destring just appears to be what you have in mind as the next step.
If your goal is, given a string variable year, to produce a daily date variable for 31 December in each year, then destring is not necessary. Here are three ways to do it:
gen date = daily("31 Dec" + year, "DMY")
gen date = date("31 Dec" + year, "DMY")
gen date = mdy(12, 31, real(year))
Incidentally, there is no likely gain for Stata use in daily dates 365 or 366 days apart, as they just create a time series that is mostly implicit gaps.
If your data are yearly, but just associated with the end of each calendar year, keep them as yearly and use a display format to show "31 Dec", or the equivalent, in output.
. di %ty!3!1_!D!e!c_CCYY 2015
31 Dec 2015
Detail. date() is a function, not a command, in Stata. We can't comment on "does not seem to work" as no details are given of what you tried or what happened. daily() is just a synonym for date().
I am currently trying to change the format of a date from "2010-01-11 00:00:00" to "01-11-2010" or "1/11/2010". Currently "2010-01-11 00:00:00" is in a string format. I have tried to coerce using the date() function but it never returns to the point where Stata can recognize and sort. Would anyone have any idea how to do this?
It's best if for future questions you post attempted code and why it's not working for you.
Maybe this works in your case:
clear all
set more off
*----- example data -----
set obs 1
gen dat = "2010-01-11 00:00:00"
describe
list
*----- what you want -----
gen double dat2 = clock(dat, "YDM hms")
format dat2 %tcDD-NN-YY
describe
list
Note that we go from string type to numeric type (double), and then adjust the display format.
See help format, help datetime and help datetime_display_formats.
Read also:
Stata tip 113: Changing a variable's format: What it does and does not mean
N. J. Cox. 2012.
Stata Journal Volume 12 Number 4.
http://www.stata-journal.com/article.html?article=dm0067
If you are ingesting time data in "2010-01-11 00:00:00" (SQL) format, then by default it is ingested into Stata as a str23
If you would like it as a Stata date format to manipulate, you could try the following (ingested_date_1 ... being your date columns)
foreach sqltime in ingested_date_1 ingested_date_2 {
rename `sqltime' X
generate double `sqltime' = clock(X, "YMD hms")
drop X
format %tcDDmonCCYY_HH:MM:SS `sqltime'
}
This, takes in multiple "dates", just replace your column names with ingested_date_1 ingested_date_2 etc and reformats them and keeps their 'original' name
Now the dates are in a stata recognised time format, %tc based of the clock, this will be sorted in the time-sense like you expect, rather than the ingested string which was not.
Additionally you may now reformat the display of the date to something that you would like or are comfortable reading, although it will make no difference to date manipulation, it is just the displayed appearance, in the case of viewing as "01-11-2010"
as Roberto says
format ingetsed_date_i %tcDD-NN-YY