I am trying to plot the US yield curve on a graph but I would like the ticks of the x-axis to be nearer until 1 year, then normal. I have not found how to solve it. Does anyone know?
My data set is :
Interest | February | August |
---|---|---|
1 Mo | 2.186 | 0.035 |
3 Mo | 2.626 | 0.279 |
6 Mo | 3.128 | 0.590 |
1 Y | 3.290 | 0.900 |
2 Y | 3.214 | 1.368 |
3 Y | 3.149 | 1.631 |
5 Y | 2.923 | 1.824 |
10 Y | 2.864 | 1.924 |
20 Y | 2.774 | 2.323 |
30 Y | 2.999 | 2.253 |
I have a graph so with the following code:
a$level_order <- factor(a$Interest, c('1 Mo', '3 Mo', '6 Mo','1 Y','2 Y','3 Y', '5 Y','7 Y', '10 Y', '20 Y', '30 Y'))
ggplot(a, aes(x=level_order,y=August,group=1))
geom_line(color="darkred")
geom_point(color="darkred")
geom_point(aes(y=February),color="darkblue")
geom_line(aes(y=February),color="darkblue")
theme_bw()
What I would like to get look like it ( a steeper slope before 1 Year) with 1 Mo 3 Mo 6 Mo pretty near.
CodePudding user response:
The problem is you are using as x-axis a list of factors and ggplot take them as discrete data, plotting them with equal distance.
You can use
scale_x_discrete()
and manually write every break and every label for each break which is a bit tedious and you have to re-adapt it if you add new rows.You can create a new numeric -continuous- column from your character/factor column
Interest
with the same magnitude and then usescale_x_continuous()
.
Example:
example = data.frame(
Interest = c('1 Mo', '2 Mo', '6 Mo', '1 Y', '2 Y', '5 Y'),
February = c(2.186,2.626,3.128,3.290,3.214,2.923),
August = c(0.035,0.279,0.590,0.900,1.368,1.824)
)
library(dplyr)
example %>% # use extract() to quickly split numbers and letters
extract(Interest, into=c("Num", "time"), "([0-9]*)(.*)") %>%
mutate(Num = as.numeric(Num),
Year_period = ifelse(time == " Mo", Num/12, Num)) %>% # change months magnitude to years
ggplot(aes(x=Year_period,y=August,group=1))
geom_line(color="darkred")
geom_point(color="darkred")
geom_point(aes(y=February),color="darkblue")
geom_line(aes(y=February),color="darkblue")
scale_x_continuous(name="Years",breaks = seq(1,5,1), labels = str_c(seq(1,5,1),"Y")) # Here you re-scale the x-axis
theme_bw()
Within scale_x_continuous()
, breaks=
says where to tick the labels, giving an array of integers for the years, labels=str_c(seq(1,5,1),"Y"))
is creating the names for each tick. Because all "Mo" rows are divided by 12, so < 1, now the x-axis is transformer to represent years.
Output. Note I haven't use the whole data. Adapt breaks
and labels
for all your rows (if your max year is '30Y' then breaks = seq(1,30,1)
and labels=str_c(seq(1,30,1),"Y"))
. Now the first values ('Mo') are closer and < '1Y' .
CodePudding user response:
There isn't a great way to do this natively, since the tidyverse philosophy is opposed to this kind of false scaling. The "correct" way to do this is to have a consistent axis, either linear or log-scaled.
That being said, while it's a bit hacky, we achieve what you want by creating a pre-scaled integer scale for the x-axis:
b <- a %>%
group_by(yr = grepl('Y$', Interest)) %>%
mutate(level = row_number(),
level = if_else(yr, as.integer(3*level 1), level))
This gives us this table where each position on level
is a consistent distance on the x-axis, while yr
identifies the values which should have a tick.
Interest February August yr level
<chr> <dbl> <dbl> <lgl> <int>
1 1 Mo 2.19 0.035 FALSE 1
2 3 Mo 2.63 0.279 FALSE 2
3 6 Mo 3.13 0.59 FALSE 3
4 1 Y 3.29 0.9 TRUE 4
5 2 Y 3.21 1.37 TRUE 7
6 3 Y 3.15 1.63 TRUE 10
7 5 Y 2.92 1.82 TRUE 13
8 10 Y 2.86 1.92 TRUE 16
9 20 Y 2.77 2.32 TRUE 19
10 30 Y 3.00 2.25 TRUE 22
Now, we can just plot with a continuous x-axis, using the values of level
for breaks and Interest
for labels, with yr
determining whether to show the label or not (you can drop that selector if you want to show the ticks for the monthly intervals):
ggplot(b, aes(x=level,y=August,group=1))
geom_line(color="darkred")
geom_point(color="darkred")
geom_point(aes(y=February),color="darkblue")
geom_line(aes(y=February),color="darkblue")
scale_x_continuous(breaks=b$level[b$yr],
labels=b$Interest[b$yr])
theme_bw()