R - XTS: Get the first dates and values for each month from a daily time series with missing rows

StackOverflow https://stackoverflow.com/questions/22592193

  •  19-06-2023
  •  | 
  •  

Question

I have a daily time series as a myxts xts object in R, with date format being d/m/y. Now, I want to reduce the original time series to one that only takes the first date and value for each month in the series.

myxts[.indexmday(myxts) == 1] returns a series containing d/m/y with d = 1.

My problem is that I need 1 data for each month and my problem is that my original series has some months with no date and data for the date 1st calendar date.

How does I say to R if there is not such a date, then takes the 2nd day for this particular month, and if the latter is not available then take the third, and so on ...

Eg, in the example data below, there is no Feb 1st, 2014. There is no Jan 1st either.

dates <- c('14/02/2014', '13/02/2014', '12/02/2014', '11/02/2014', '10/02/2014', '07/02/2014', '06/02/2014', '05/02/2014', '04/02/2014', '03/02/2014', '31/01/2014', '30/01/2014', '29/01/2014', '28/01/2014', '27/01/2014', '24/01/2014', '23/01/2014', '22/01/2014', '21/01/2014', '20/01/2014', '17/01/2014', '16/01/2014', '15/01/2014', '14/01/2014', '13/01/2014', '10/01/2014', '09/01/2014', '08/01/2014', '07/01/2014', '06/01/2014', '03/01/2014', '02/01/2014', '31/12/2013', '30/12/2013', '27/12/2013', '26/12/2013', '24/12/2013', '23/12/2013', '20/12/2013', '19/12/2013', '18/12/2013', '17/12/2013', '16/12/2013', '13/12/2013', '12/12/2013', '11/12/2013', '10/12/2013', '09/12/2013', '06/12/2013', '05/12/2013', '04/12/2013', '03/12/2013', '02/12/2013', '29/11/2013', '28/11/2013', '27/11/2013', '26/11/2013', '25/11/2013', '22/11/2013', '21/11/2013', '20/11/2013', '19/11/2013', '18/11/2013', '15/11/2013', '14/11/2013', '13/11/2013', '12/11/2013', '11/11/2013', '08/11/2013', '07/11/2013', '06/11/2013', '05/11/2013', '04/11/2013', '01/11/2013', '31/10/2013', '30/10/2013', '29/10/2013', '28/10/2013', '25/10/2013', '24/10/2013', '23/10/2013', '22/10/2013', '21/10/2013', '18/10/2013', '17/10/2013', '16/10/2013', '15/10/2013', '14/10/2013', '11/10/2013', '10/10/2013', '09/10/2013', '08/10/2013', '07/10/2013', '04/10/2013', '03/10/2013', '02/10/2013', '01/10/2013', '30/09/2013', '27/09/2013', '26/09/2013', '25/09/2013', '24/09/2013', '23/09/2013', '20/09/2013', '19/09/2013', '18/09/2013', '17/09/2013', '16/09/2013', '13/09/2013', '12/09/2013', '11/09/2013', '10/09/2013', '09/09/2013', '06/09/2013', '05/09/2013', '04/09/2013', '03/09/2013', '02/09/2013', '30/08/2013', '29/08/2013', '28/08/2013', '27/08/2013', '26/08/2013', '23/08/2013', '22/08/2013', '21/08/2013', '20/08/2013', '19/08/2013', '16/08/2013', '15/08/2013', '14/08/2013', '13/08/2013', '12/08/2013', '09/08/2013', '08/08/2013', '07/08/2013', '06/08/2013', '05/08/2013', '02/08/2013', '01/08/2013', '31/07/2013', '30/07/2013', '29/07/2013', '26/07/2013', '25/07/2013', '24/07/2013', '23/07/2013', '22/07/2013', '19/07/2013', '18/07/2013', '17/07/2013', '16/07/2013', '15/07/2013', '12/07/2013', '11/07/2013', '10/07/2013', '09/07/2013', '08/07/2013', '05/07/2013', '04/07/2013', '03/07/2013', '02/07/2013', '01/07/2013', '28/06/2013') 
values <- c(920.25, 918.5, 921.5, 921.5, 921, 919, 906.25, 899, 906.25, 903, 917, 924, 923.75, 917.5, 914.5, 921.75, 922.5, 919, 919, 907.75, 916.25, 907.5, 913.75, 900.25, 907, 907.25, 907.25, 912.25, 910.5, 910.25, 910.25, 923.5, 944.25, 945.5, 955.75, 950, 944.25, 945.75, 945.25, 935.25, 929, 919.5, 931.5, 917.75, 932, 932, 928, 934.25, 940.75, 943.75, 947.25, 945.75, 942.75, 943, 942, 941, 944.5, 934.75, 937.75, 923.25, 911, 910.75, 910.25, 911.25, 908.75, 901.25, 903.25, 903.25, 893, 888.5, 905, 903, 904, 915, 932.5, 937.25, 930.5, 925.75, 909.75, 911.5, 920, 936.5, 941.5, 939.25, 931.5, 945, 940.25, 931.5, 933.5, 925.25, 925.25, 935.5, 926.25, 922.5, 926.5, 922.5, 905.25, 913, 927.25, 920.5, 919, 906, 913, 925.25, 934.5, 924.25, 925.75, 944.25, 949.75, 943.5, 943.5, 938.75, 960, 971, 963.75, 960.75, 960.25, 958.5, 969.5, 978.75, 970, 961.75, 940.25, 941.75, 936.25, 938.75, 938.75, 942.25, 941.25, 937.25, 926, 927.75, 903.75, 903.75, 896, 906, 909.25, 920.25, 923.75, 927, 910.5, 908, 913.75, 910.5, 913.75, 914.25, 919.75, 918.5, 925.75, 928.75, 923.75, 919.75, 916.5, 916.25, 913.75, 913.75, 909.25, 913.25, 911.75, 902.25, 903.25, 879.75, 883.25, 883.25)
myxts <- as.xts(values, order.by = as.Date(dates, format = '%d/%m/%Y'))
Was it helpful?

Solution

There is an unexported startof function that could be useful here

myxts[xts:::startof(myxts, "months")]
             [,1]
2013-06-28 883.25
2013-07-01 883.25
2013-08-01 927.00
2013-09-02 958.50
2013-10-01 905.25
2013-11-01 915.00
2013-12-02 942.75
2014-01-02 923.50
2014-02-03 903.00

OTHER TIPS

You can use period.apply or the monthly wrapper here:

apply.monthly(myxts,head,1)
             [,1]
2013-06-28 883.25
2013-07-31 883.25
2013-08-30 927.00
2013-09-30 958.50
2013-10-31 905.25
2013-11-29 915.00
2013-12-31 942.75
2014-01-31 923.50
2014-02-14 903.00

EDIT using endpoints ( it is mainly the code startof function presented in the other solution)

 myxts[head(endpoints(myxts, "months") + 1, -1)] ## edited as Gsee comment

             [,1]
2013-06-28 883.25
2013-07-01 883.25
2013-08-01 927.00
2013-09-02 958.50
2013-10-01 905.25
2013-11-01 915.00
2013-12-02 942.75
2014-01-02 923.50
2014-02-03 903.00
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top