Depending on the input of my code - a varying number of columns are populated. I am attempting to create a loop which will only populate the columns which are populated. However, i am struggling as the loop keep overwriting and only retains the last line plotted on the graph. I though printing the ggplot would help - but sadly not!
plot <- ggplot(plottable, aes(x = Date))
####for (i in 2:ncol(plottable)) {
for (i in 2:ncol(plottable)) {
Exposure <- assign(colnames(plottable)[i],plottable[,i])
plot <- plot +
geom_line(aes(y=Exposure, color = colnames(plottable)[i]))
print(plot)
}
plot
Data
structure(list(Date = structure(c(18078, 18079, 18080, 18081, 18082), class = "Date"), Zone9 = c(0, 0, 0, 0, 0), Zone6 = c(0, 0, 0, 0, 0), Zone4 = c(0, 0, 0, 0, 0), Zone3 = c(0, 969698.444, 969698.444, 969698.444, 969698.444), Zone2 = c(0, 0, 0, 0, 0), Zone11 = c(0, 15560719.2483794, 15560719.2483794, 15560719.2483794, 15560719.2483794), Zone10 = c(0, 2208064.625714, 2208064.625714, 2208064.625714, 2208064.625714), Zone1 = c(0, 0, 0, 0, 0)), row.names = c(NA, 5L), class = "data.frame")
Personally I would follow the approach using tidyr::pivot_longer as outlined by #AndyEggers. Nonetheless if you don't want to reshape your dataset you could add multiple geom layers to a plot using e.g. lapply or purrr::map like so:
ggplot(plottable, aes(x = Date)) +
lapply(names(plottable)[!names(plottable) %in% "Date"], function(x) {
geom_line(aes(y=.data[[x]], color = x))
})
Making use of ggplot2::economics as example data:
library(ggplot2)
ggplot(economics, aes(x = date)) +
lapply(names(economics)[!names(economics) %in% "date"], function(x) {
geom_line(aes(y=.data[[x]], color = x))
})
Your approach looks like something I would have tried before I got comfortable with tidyr and ggplot. I suggest a different approach that makes better use of these tools:
plottable %>%
pivot_longer(cols = -Date) %>%
ggplot(aes(x = Date, y = value, col = name)) +
geom_line()
Related
I am new in R, so my question could seem very trivial for someone, but I need a solution. I have a data frame:
`structure(list(Time = c(0, 0, 0), Node = 1:3, Depth = c(0, -10,
-20), Head = c(-1000, -1000, -1000), Moisture = c(0.166, 0.166,
0.166), HeadF = c(-1000, -1000, -1000), MoistureF = c(0.004983,
0.004983, 0.004983), Flux = c(-0.00133, -0.00133, -0.00133),
FluxF = c(-0.00122, -0.00122, -0.00122), Sink = c(0, 0, 0
), Transf = c(0, 0, 0), TranS = c(0, 0, 0), Temp = c(20,
20, 20), ConcF = c(0, 0, 0), ConcM = c(0, 0, 0)), row.names = c(NA,
3L), class = "data.frame")`.
I am able to plot a single TranS vs Time Single plot, where color = Transf (using scale_color_viridis). I want to create plots with a filtered data for( depth = -20, depth = -40 , -60, -80 and -100) Note: that title also have to be changed according to a depth value. These plots then I want to put next to each other using facet_grid.
I have tried in a such way:
plot_d20 <-plot_node %>% filter(plot_node$Depth == -20)
plot_d40 <-plot_node %>% filter(plot_node$Depth == -40)
plot_d60 <-plot_node %>% filter(plot_node$Depth == -60)
plot_d80 <-plot_node %>% filter(plot_node$Depth == -80)
plot_d100 <-plot_node %>% filter(plot_node$Depth == -100)
depth_plot <- c(plot_d20,plot_d40,plot_d60,plot_d80,plot_d100)
for (p in depth_plot){
ggpS<-ggplot(p, aes(Time, TranS, color=Transf) ) +
geom_point(alpha = 1)+
scale_color_viridis(option = "D")+
scale_x_continuous(limits = c(0,1400), breaks = seq(0,1400,200))+
ggtitle('Solute Mass Transfer for depth = 20mm')
ggpS
}
But it doesn't work.
R says:
data must be a data frame, or another object coercible by fortify(), not a numeric vector. And I don't know how to make my title dynamic and combine it with facet_grid or on a single plot, but in this case, I will face difficulty to distinguish the lines and assigning the legend to the plot by color, because color already represents another variable. What is the possible way to accomplish that?
Edit: Understand the question differently.
facet_grid accepts a single data.frame, and uses one of that frames values to split a chart into multiple subplots. Your question describes combining multiples charts into a single chart, which is available as a function from the cowplot library. However, If you are interested in faceting the data, here is a way to filter and facet_wrap.
Example with Iris data:
library(tidyverse)
iris %>%
filter(Sepal.Length %in% c(6.4,5.7,6.7,5.1,6.3,5)) %>% ### Your values here
ggplot(aes(Petal.Length, Petal.Width, color=Species)) +
geom_point(alpha = 1) +
scale_color_viridis_d()+ #(option = "D") + ### New function name
#scale_x_continuous(limits = c(0,1400), breaks = seq(0,1400,200))+
facet_wrap("Sepal.Length") +
# facet_grid("Sepal.Length") + ### Alternative Layout
ggtitle('Sepal Length Range')
To create a "grid" of plots with only one faceting variable, you'll actually want to use facet_wrap(). You can create your facet titles before plotting, and change the formatting of strip.text within theme() to make them look more "title-like."
library(dplyr)
library(ggplot2)
plot_node %>%
mutate(
facet = paste0("Solute Mass Transfer for Depth = ", abs(Depth), "mm")
) %>%
ggplot(aes(Time, TranS, color=Transf)) +
geom_point(alpha = 1) +
scale_color_viridis_c(option = "D") +
scale_x_continuous(limits = c(0, 1400), breaks = seq(0, 1400, 200)) +
facet_wrap(vars(facet), ncol = 2, scales = "free") +
theme_minimal() +
theme(strip.text = element_text(size = 12, face = "bold"))
I'm just starting with R visuals, and I'm stuck on this one. In the code below you will find the table I'm working with and its rendering.
What I'm trying to do is to obtain a horizontal bar chart where for each Pool value I have two variables (D_MTD and I_MTD).
To achieve that (and I don't know if this is the right way of doing it) I added two geom_bar layers and what I get is pretty much what it should look like (it's okay to have stacked columns).
MyTable <- data.frame(
Pool = c(" ", "(CA) Domestic", "(CA) International", "(FR) International", "(US) Domestic", "(US) International" ),
ADomestic = c(0, 36000, 3000, 1200, 54000, 6000),
AInternational = c(0, 0, 600, 600, 0, 1200),
D_MTD = c(23.4, 0, 0, 0, 8.38, 0),
I_MTD = c(6.63, 0, 0, 0, 0, 0)
)
MyTable
MyVisual <- MyTable %>%
ggplot(
Data = MyTable,
aes(y = Pool)
) +
geom_bar(
aes(
weight = D_MTD,
colour = "Domestic"
),
alpha = 0.5
) +
geom_bar(
aes(
weight = I_MTD,
colour = "International"
),
alpha = 0.5
) +
labs(
title = "Month-To-Date Consumption by Pool",
subtitle = "(in minutes)",
y = "Pools",
x = "MTD Used Minutes",
colour = "Pool context"
)
MyVisual
However, the visual has two outline colours that I don't want (I would like the bars to be filled with colors instead). I tried to use the fill argument to assign a fixed color to the bars (ex: red for Domestic and blue for International) but that generates another legend that I don't want to show.
Example:
MyVisual <- MyTable %>%
ggplot(
Data = MyTable,
aes(y = Pool)
) +
geom_bar(
aes(
weight = D_MTD,
colour = "Domestic",
fill = "red"
),
alpha = 0.5
) +
geom_bar(
aes(
weight = I_MTD,
colour = "International",
fill = "blue"
),
alpha = 0.5
) +
labs(
title = "Month-To-Date Consumption by Pool",
subtitle = "(in minutes)",
y = "Pools",
x = "MTD Used Minutes",
colour = "Pool context"
)
MyVisual
Also, how do I apply labels to each bar with the corresponding values?
Thanks in advance!
This solution should work for you. It contains elements, and transformation that for a starter may be confusing, but you will have to face these at some point. I recommend you to read the book R for Data Science, at least the chapter reated to data visualization with ggplot2.
Steps:
1- Reshape the data usin the pivot_longer() function
2- Creating factors and labels for the plot
library(tidyr)
library(dplyr)
library(ggplot2)
MyTable <- data.frame(
Pool = c(" ", "(CA) Domestic", "(CA) International", "(FR) International", "(US) Domestic", "(US) International" ),
ADomestic = c(0, 36000, 3000, 1200, 54000, 6000),
AInternational = c(0, 0, 600, 600, 0, 1200),
D_MTD = c(23.4, 0, 0, 0, 8.38, 0),
I_MTD = c(6.63, 0, 0, 0, 0, 0)
)
to_plot <- MyTable %>%
select(Pool, D_MTD, I_MTD) %>%
# Data to long format
pivot_longer(
cols = contains('MTD'),
names_to = 'pool_context',
values_to = 'used_minutes'
) %>%
mutate(
pool_context = factor(
pool_context, c('D_MTD', 'I_MTD'), c('Domestic', 'International')
),
# Labels only for non 0 values
label = ifelse(used_minutes == 0, NA, used_minutes)
)
to_plot %>%
ggplot(aes(y = Pool, x = used_minutes)) +
# Fill aesthetic only for bars, to avoid labels to get color too
geom_col(aes(fill = pool_context)) +
theme(legend.position = 'bottom') +
geom_label(aes(label = label), hjust = 1.1) +
labs(fill = NULL, x = 'Used minutes (MTD)', y = 'Pool')
Created on 2022-02-17 by the reprex package (v2.0.1)
I am trying to combine fraction with value calculated elsewhere. I tried to combine it with expression and paste but didn't work. any suggestions please?
library(ggplot2)
Changing_Value <- 150
ggplot(data=data.frame(x=0,y=0))+
annotate('text', x = 0, y = 0,
label = "P^{frac(-1,K)}== Changing_Value ",parse = TRUE,size=7)
You can use sprintf. See the help file to see what other options are besides %d.
ggplot(data = data.frame(x = 0, y = 0)) +
annotate("text", x = 0, y = 0,
label = sprintf("P^{frac(-1,K)}== %d", Changing_Value),
parse = TRUE, size = 7)
Use paste to generate the string:
library(ggplot2)
Changing_Value <- 150
ggplot(data=data.frame(x=0,y=0))+
annotate('text', x = 0, y = 0,
label = paste("P^{frac(-1,K)}==",Changing_Value),parse = TRUE,size=7)
Or you can use glue
ggplot(data = data.frame(x = 0, y = 0)) +
annotate("text", x = 0, y = 0,
label = glue::glue("P^frac(-1,K)=={Changing_Value}"),
parse = TRUE, size = 7)
I am trying to write the base R code, using tidyverse style.
I know this question, it just did not work for me for some reasons.
> dput(my_df)
c(0.492476485097794, 0, -0.0571584138399486, -0.348306694268216,
0.510825623765991, -0.0512932943875506, -0.0540672212702757,
-0.325422400434628, 0.526093095896779, 0, -0.0465200156348928,
-0.336472236621213, 0.550046336919272, 0, -0.0800427076735366,
-0.287682072451781, 0.51082562376599, 0, -0.0689928714869512,
-0.287682072451781, 0.481838086892739, 0, -0.060624621816435,
-0.287682072451781, 0.432864082296279, 0, -0.0555698511548109,
-0.336472236621213, 0.470003629245736, 0.0246926125903714,
-0.075985906977922,
-0.305381649551182, 0.517943091534855, 0, -0.0434851119397388,
-0.31015492830384, 0.473784352085642, -0.0190481949706944,
-0.0392207131532814,
-0.2484613592985, 0.413975797776073, 0.0168071183163813, 0,
-0.22314355131421,
0.362905493689368, 0.0143887374520996, -0.0143887374520996,
-0.191055236762709,
0.375789339962048, -0.0121213605323448, -0.0500104205746613,
-0.152016207298626, 0.370018359112417, -0.0421114853501268,
-0.0666913744986723,
-0.175448677506193, 0.304660408986199, -0.010152371464018, 0,
-0.190518323998133, 0.359141036433926, -0.0996298409488412,
0.00947874395454378,
-0.186102279633861, 0.358945092473272, -0.0655972824858133,
-0.00851068966790863,
-0.218879152527752, 0.292987124681474, -0.091349778588228, 0.042559614418796,
-0.162518929497775, 0.234839591077401, -0.064021858764931,
0.0163938097756764,
-0.177455367142782, 0.270545790208794)
I did some work in base R, finding characteristic polynomial roots and drawing the circle.
But I really want to do it, using ggplot2, just do not know how.
My base R code is:
library(plotrix)
gdpDiff <- diff(my_df)
m1 = ar(gdpDiff, method = 'mle')
m1$order
m1$x.mean
m1$ar
p1 = c(1, -m1$ar)
r1 = polyroot(p1)
r1
r1Re <- Re(r1)
r1Im <- Im(r1)
Mod(r1)
plot(r1Re, r1Im, asp = 1, xlim = c(min(r1Re), max(r1Re)), ylim = c(min(r1Im), max(r1Im)))
draw.circle(0, 0, radius = 1)
abline(v = 0)
abline(h = 0)
My current result is (with 4 dots):
Any chance to do the same, using ggplot? I would greatly appreciate your help.
While this is not entirely with ggplot2, the package ggforce has a function (geom_circle) for making circles. You can use that. I have written a function to convert the real and imaginary parts into a tibble and you can then use it to plot further:
library(ggplot2)
library(ggforce)
library(plotrix)
poly_fun <- function(my_vector) {
gdpDiff <- diff(my_vector)
m1 <- ar(gdpDiff, method = 'mle')
p1 <- c(1, -m1$ar)
r1 <- polyroot(p1)
tibble(
real = Re(r1),
imaginary = Im(r1)
)
}
df <- poly_fun(my_df)
ggplot() +
geom_circle(data = tibble(x = 0, y = 0), aes(x0 = x, y0 = y, r = 1)) +
geom_point(data = df, aes(x = real, y = imaginary)) +
xlim(min(df$real), max(df$real)) +
ylim(min(df$imaginary), max(df$imaginary)) +
coord_fixed(ratio = 1) +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0)
I have a data frame with the following columns: product_id, ..., p1, p2, p3, ... etc. The p-columns only have 0 or 1 as their cell data.
I want a bar chart that sums up (or count) p1, p2 etc. and shows each p-column as a bar with the value of the sum (with ggplot).
Additionally I want to fill the color by product_id.
It seems like reshaping the data in the long format could be helpful, but I still stuck.
Here's the minimal data set, already reshaped:
product_id <- c(1, 2, 3, 1, 2, 3, 1, 2, 3)
p1 <- c(0, 0, 1, 1, 0, 0, 1, 0, 0)
p2 <- c(1, 0, 1, 0, 1, 0, 1, 1, 0)
p3 <- c(0, 0, 1, 1, 0, 1, 0, 1, 1)
df1 <- data.frame(product_id, p1, p2, p3)
df2 <- melt(df1, id.vars = "product_id",
measure.vars = grep("^p[0-9]", names(df1), value = TRUE),
variable.name = "p",
value.name = "p-active")
There are dozens of ggplot2 tutorials, but I'm feeling generous:
ggplot(df2,
#map columns to aesthetics:
aes(x = p, y = `p-active`,
#important to use a factor for discrete values:
fill = factor(product_id),
color = factor(product_id))) +
#summarize data:
stat_summary(fun.y = sum,
#the geom:
geom = "bar",
#positioning:
position = "dodge")
I'm not sure I understood exactly what you want, but I'll give it a try:
I changed the reshaping a bit, because it is not a good idea to use - in the name of a data frame column:
df2 <- melt(df1, id.vars = "product_id",
measure.vars = grep("^p[0-9]", names(df1), value = TRUE),
variable.name = "p",
value.name = "p_active")
The next step is to sum up the values in p_active per value for p and product_id:
library(dplyr)
df2_summed <- group_by(df2, product_id, p) %>%
summarise(p_active_summed = sum(p_active))
And finally, I create the plot:
library(ggplot2)
ggplot(df2_summed, aes(x = p, y = p_active_summed, fill = as.factor(product_id))) +
geom_col()