Given dataframes df1 and df2 as follows:
df1:
df1 <- structure(list(date = structure(c(1L, 2L, 4L, 5L, 6L, 7L, 8L,
9L, 10L, 11L, 3L), .Label = c("2021/1/31", "2021/2/1", "2021/2/10",
"2021/2/2", "2021/2/3", "2021/2/4", "2021/2/5", "2021/2/6", "2021/2/7",
"2021/2/8", "2021/2/9"), class = "factor"), value1 = c(9.76,
9.76, 9.88, 9.31, 9.71, 9.56, 9.27, 9.22, 9.21, 9.08, 8.78),
value2 = c(6.84, 6.88, 6.95, 6.65, 6.94, 6.85, 6.66, 6.66,
6.6, 6.5, 6.25), value3 = c(6.33, 6.21, 6.31, 6.2, 6.56,
6.36, 6.36, 6.25, 6.1, 6.02, 5.76), value4 = c(10.68, 10.91,
11, 10.49, 10.8, 10.5, 10.2, 9.85, 10.03, 9.8, 9.51), value5 = c(7.77,
7.84, 7.83, 7.44, 7.83, 7.77, 7.6, 7.46, 7.46, 7.39, 7.29
)), class = "data.frame", row.names = c(NA, -11L))
df2:
df2 <- structure(list(type = structure(c(2L, 2L, 3L, 3L, 1L), .Label = c("pct_change",
"price", "quantity"), class = "factor"), columns = structure(1:5, .Label = c("value1",
"value2", "value3", "value4", "value5"), class = "factor"), unit = structure(c(3L,
3L, 1L, 1L, 2L), .Label = c("", "%", "$"), class = "factor")), class = "data.frame", row.names = c(NA,
-5L))
With code below, I'm able to loop all columns based df2
, which means for each columns, if its type are identical, then plot them on same plot and finally save them with name of type.
library(ggplot2)
library(data.table)
df1$date <- as.Date(df1$date)
df1.m <- melt(df1, id = "date") # convert to long format
# add "type" variable to df1.m
df1.m2 = merge(df1.m, df2, by.x = "variable", by.y = "columns")
# for each "type", filter the data to that type, plot, and save
for(my_type in unique(df1.m2$type)) {
g <- ggplot(data = df1.m2[df1.m2$type == my_type,],
aes(x=date, y = value, colour=variable))
geom_line(size = 1, alpha = 1)
print(g)
# ggsave(paste0(my_type,".png"))
}
Now I hope to reset ylab()
for each plot, which means if its type is identical, then set its ylab()
using unit
from df2
.
I try code below, but it's not working:
for(my_type in unique(df1.m2$type))
for (my_unit in unique(df1.m2$unit)){
g <- ggplot(data = df1.m2[df1.m2$type == my_type,],
aes(x=date, y = value, colour=variable))
ylab(my_unit)
geom_line(size = 1, alpha = 1)
print(g)
# ggsave(paste0(my_type,".png"))
}
How could I achieve that based on code above? Sincere thanks at advance.
CodePudding user response:
Not sure what you tried with the nested for
. As far as I get it you could achieve your desired result by using the unique(unit)
of your filtered dataset as the label for y
scale:
library(ggplot2)
for(my_type in unique(df1.m2$type)) {
d <- df1.m2[df1.m2$type == my_type,]
g <- ggplot(data = d,
aes(x=date, y = value, colour=variable))
geom_line(size = 1, alpha = 1)
labs(y = unique(d$unit))
print(g)
}
CodePudding user response:
Here's an alternative approach which avoids looping through the dataframe altogether.
Convert
df1
to long format and renamename
tocolumns
Join to
df2
oncolumns
Mutate column
type
to include the unitsPlot value versus date, color by
columns
and facet bytype
Make some theme adjustments to display type and units on each facet axis
library(ggplot2) library(dplyr) library(tidyr) df1 %>% pivot_longer(2:6, names_to = "columns") %>% left_join(df2) %>% mutate(type = paste(type, unit)) %>% ggplot(aes(date, value)) geom_line(aes(color = columns, group = columns)) facet_grid(type ~ ., switch = 'y', scales = "free_y") theme(axis.title.y = element_blank(), strip.background = element_rect(fill = 'transparent'), strip.placement = 'outside', strip.text.y = element_text(angle=180))
Result:
CodePudding user response:
for(my_type in unique(df1.m2$type)) {
g <- ggplot(
data = df1.m2[type == my_type],
aes(x=date, y = value, colour=variable)
)
scale_y_continuous(labels = function(x) {
if(my_type == "price") {
paste("$", x)
} else if(my_type == "pct_change") {
paste(x, "%")
} else {
x
}
})
geom_line(size = 1, alpha = 1)
print(g)
# ggsave(paste0(my_type,".png"))
}