Question

I have some data in a wide format. How do I convert the data in the long format? Input would look like as given below:

> require("FRBData")
> curve.wide <- GetInterestRates("TCMNOM", lastObs = 5)
> curve.wide
             1M   3M   6M   1Y   2Y   3Y   5Y   7Y  10Y  20Y  30Y
2014-01-17 0.01 0.05 0.07 0.11 0.40 0.79 1.64 2.27 2.84 3.50 3.75
2014-01-21 0.01 0.04 0.07 0.12 0.40 0.81 1.67 2.29 2.85 3.50 3.74
2014-01-22 0.00 0.04 0.07 0.11 0.44 0.85 1.72 2.34 2.87 3.52 3.75
2014-01-23 0.01 0.04 0.05 0.11 0.39 0.77 1.62 2.24 2.79 3.44 3.68

Output would be something like this:

> Date = rep(index(curve.treasury), ncol(curve.treasury))
> Maturities = rep(colnames(curve.treasury), each = nrow(curve.treasury))
> Rates = as.vector(curve.treasury)
> curve.long = data.frame(Date, Maturities, Rates)
> curve.long
         Date Maturities Rates
1  2014-01-17         1M  0.01
2  2014-01-21         1M  0.01
3  2014-01-22         1M  0.00
4  2014-01-23         1M  0.01
5  2014-01-17         3M  0.05
6  2014-01-21         3M  0.04
7  2014-01-22         3M  0.04
8  2014-01-23         3M  0.04
9  2014-01-17         6M  0.07
10 2014-01-21         6M  0.07
11 2014-01-22         6M  0.07
12 2014-01-23         6M  0.05
13 2014-01-17         1Y  0.11
14 2014-01-21         1Y  0.12
15 2014-01-22         1Y  0.11
16 2014-01-23         1Y  0.11
17 2014-01-17         2Y  0.40
18 2014-01-21         2Y  0.40
19 2014-01-22         2Y  0.44
20 2014-01-23         2Y  0.39
21 2014-01-17         3Y  0.79
22 2014-01-21         3Y  0.81
23 2014-01-22         3Y  0.85
24 2014-01-23         3Y  0.77
25 2014-01-17         5Y  1.64
26 2014-01-21         5Y  1.67
27 2014-01-22         5Y  1.72
28 2014-01-23         5Y  1.62
29 2014-01-17         7Y  2.27
30 2014-01-21         7Y  2.29
31 2014-01-22         7Y  2.34
32 2014-01-23         7Y  2.24
33 2014-01-17        10Y  2.84
34 2014-01-21        10Y  2.85
35 2014-01-22        10Y  2.87
36 2014-01-23        10Y  2.79
37 2014-01-17        20Y  3.50
38 2014-01-21        20Y  3.50
39 2014-01-22        20Y  3.52
40 2014-01-23        20Y  3.44
41 2014-01-17        30Y  3.75
42 2014-01-21        30Y  3.74
43 2014-01-22        30Y  3.75
44 2014-01-23        30Y  3.68

Is there a better way to achieve this? Are there any existing functions or libraries to perform this find of transformation?

Was it helpful?

Solution

Using reshape2::melt():

# read data
curve.wide <- read.table(sep=" ", header=T, text="1M 3M 6M 1Y 2Y 3Y 5Y 7Y 10Y 20Y 30Y
2014-01-17 0.01 0.05 0.07 0.11 0.40 0.79 1.64 2.27 2.84 3.50 3.75
2014-01-21 0.01 0.04 0.07 0.12 0.40 0.81 1.67 2.29 2.85 3.50 3.74
2014-01-22 0.00 0.04 0.07 0.11 0.44 0.85 1.72 2.34 2.87 3.52 3.75
2014-01-23 0.01 0.04 0.05 0.11 0.39 0.77 1.62 2.24 2.79 3.44 3.68")
curve.wide$Date <- row.names(curve.wide)

# wide to long
require(reshape2)
curve.long <- melt(data=curve.wide, 
                   id.vars="Date", 
                   variable.name="Maturities",
                   value.name="Rates")

OTHER TIPS

You can use the data.frame function to transform the xts/zoo object into a data frame in long format.

# library(FRBData)
data.frame(Date = index(curve.wide),
           Maturities = as.vector(curve.wide),
           Rates = rep(names(curve.wide), each = nrow(curve.wide)))

         Date Maturities Rates
1  2014-01-17       0.01    1M
2  2014-01-21       0.01    1M
3  2014-01-22       0.00    1M
4  2014-01-23       0.01    1M
5  2014-01-17       0.05    3M
6  2014-01-21       0.04    3M
7  2014-01-22       0.04    3M
8  2014-01-23       0.04    3M
9  2014-01-17       0.07    6M
...

An alternative version based on stack:

setNames(cbind(index(curve.wide), 
               stack(as.data.frame(curve.wide))), 
         c("Date", "Maturities", "Rates"))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top