I have a data.frame, for example:
df = data.frame(AAA=rnorm(100,1,1),BBB=rnorm(100,2,1.5),CCC=rnorm(100,1.5,1.2))
And I'd like to plot each of its columns in a joint violin plot.
Here's where I'm at so far:
names(df)[1] = 'x'
do.call('vioplot', c(df,col="red",drawRect=FALSE))
What I want to do next is to plot the colnames of df as x-axis labels rather than the default x-axis labels of vioplot and in addition in a way that they don't run over each other. I imagine this can be achieved either by spreading the columns of df in the plot or by slanting the x-axis labels. But I can't figure that out.
Probably easier to use ggplot
df = data.frame(AAA=rnorm(100,1,1),
BBB=rnorm(100,2,1.5),
CCC=rnorm(100,1.5,1.2))
Need to transform the data into something ggplot can handle:
df.m <- reshape2::melt(df, id.vars = NULL)
and plot:
library(ggplot2)
ggplot(df.m, aes(x = variable, y = value)) + geom_violin()
I like the ggplot solution the best, but here is how you would do it with do.call:
do.call(vioplot,c(unname(df),col='red',drawRect=FALSE,names=list(names(df))))
Notably, you wouldn't have to do names(df)[1] = 'x' because you remove the names with unname.
Have you tried dropping the do.call call and doing them individually.
vioplot(df[,"AAA"], df[,"BBB"], df[,"CCC"],
col = "red", drawRect = FALSE,names = names(df))
Another simple option is using the ggviolin function from ggpubr with long formatted data like this:
df = data.frame(AAA=rnorm(100,1,1),BBB=rnorm(100,2,1.5),CCC=rnorm(100,1.5,1.2))
library(dplyr)
library(tidyr)
library(ggpubr)
df %>%
pivot_longer(cols = everything()) %>%
ggviolin(x = "name",
y = "value")
Created on 2022-08-14 by the reprex package (v2.0.1)
Related
I'm having some trouble with this conceptually.
Using the 'Decathlon' dataset from library(GDAdata) and ggplot2;
I want to make boxplots using all of the point variables, which is essentially the last half of the dataset; columns = 15:24 or P100m:P1500.
On a single plot, I want a boxplot for each of those columns on the x axis, and Totalpoints on the y axis.
Any help is appreciated! Thank you.
Here is one way to do it:
Load GDAdata::Decathlon
Make long format with pivot_longer
then use ggplot with geom_boxplot()
library(tidyverse)
library(GDAdata)
df <- GDAdata::Decathlon %>%
select(15:24) %>%
pivot_longer(
cols = everything(),
names_to = "Names",
values_to = "Values"
)
p <- ggplot(df, aes(x=Names, y=Values)) +
geom_boxplot()
p
I have a list of variables on R, each with their own numerical value. How can I set those variables so that I can plot a bar chart, whereby the variables are named along the x-axis
Example:
my_list <- list(a, b, c, d, e, f, g)
where a to g are all variables with numerical values
frame2 <- data.frame(my_list)
ggplot(data=frame2, aes(x=my_list, y=Total))+
geom_col()
Ideally, a bar chart with a to g along the x axis would appear but templates I've used so far don't work.
Should I stop using a list altogether?
Using some random example data. From your description I simply guessed that your vars contain only one(?) total value. Nevertheless in either case the trick is to convert the dataframe into long format via e.g. tidyr::pivot_longer. This way your vars can be treated as different categories of one variable which we plot on the x-axis. Try this
set.seed(42)
my_list <- list(a = runif(1), b = runif(1), c = runif(1))
frame2 <- data.frame(my_list)
library(ggplot2)
library(dplyr)
library(tidyr)
frame2 %>%
tidyr::pivot_longer(everything(), names_to = "var", values_to = "Total") %>%
ggplot(aes(x=var, y = Total, fill=var))+
geom_col(position = "dodge")
Created on 2020-04-19 by the reprex package (v0.3.0)
It is not really clear what Total is in your ggplot syntax.
Generally I would indeed not use a list, but go about it like so
my_df <- data.frame(vars = letters[1:7], value = 1:7)
ggplot(my_df, aes(x = vars, y = value)) + geom_col()
is there a way to plot percentages using plot_ly. For example, the below is used to plot the count of cut from diamonds dataset,
plot_ly(diamonds, x = ~cut)
But i tried to plot the percentage for cut. For example I need the percentage of "Good" to the total count. Is there a way to get it?
It could be done like this.
First, create percentage for each cut category
diamonds %>% group_by(cut) %>% summarize(perc = n()/53940*100)
summarized dataset
Second, pipe the resultant data set to plot_ly()
diamonds %>% group_by(cut) %>% summarize(perc = n()/53940*100) %>% plot_ly(x = ~cut, y = ~perc)
R Plot
You can use data.table and ggplot2:
library(data.table)
library(ggplot2)
dt <- data.table(diamonds)
Calculate the number of records by each cut, and then calculate the prop.table of those counts:
result <- dt[, .N, by = cut][, .(cut, N, percentCut = prop.table(N))]
Now you can plot it with ggplot and use the library scales to have a beautiful percent-formatted y-axis:
p <- ggplot(result, aes(x = cut, y = percentCut))+
geom_col()+
scale_y_continuous(labels = scales::percent)
Now you can pass p to plotly, if so you want:
plotly::ggplotly(p)
Here is a snapshot of data:
restaurant_change_sales = c(3330.443, 3122.534)
restaurant_change_labor = c(696.592, 624.841)
restaurant_change_POS = c(155.48, 139.27)
rest_change = data.frame(restaurant_change_sales, restaurant_change_labor, restaurant_change_POS)
I want two bars for each of the columns indicating the change. One graph for each of the columns.
I tried:
ggplot(aes(x = rest_change$restaurant_change_sales), data = rest_change) + geom_bar()
This is not giving the result the way I want. Please help!!
So ... something like:
library(ggplot2)
library(dplyr)
library(tidyr)
restaurant_change_sales = c(3330.443, 3122.534)
restaurant_change_labor = c(696.592, 624.841)
restaurant_change_POS = c(155.48, 139.27)
rest_change = data.frame(restaurant_change_sales,
restaurant_change_labor,
restaurant_change_POS)
cbind(rest_change,
change = c("Before", "After")) %>%
gather(key,value,-change) %>%
ggplot(aes(x = change,
y = value)) +
geom_bar(stat="identity") +
facet_grid(~key)
Which will produce:
Edit:
To be extra fancy e.g. make it so that the order of x-axis labels goes from "Before" to "After", you can add this line: scale_x_discrete(limits = c("Before", "After")) to the end of the ggplot function
Your data are not formatted properly to work well with ggplot2, or really any of the plotting packages in R. So we'll fix your data up first, and then use ggplot2 to plot it.
library(tidyr)
library(dplyr)
library(ggplot2)
# We need to differentiate between the values in the rows for them to make sense.
rest_change$category <- c('first val', 'second val')
# Now we use tidyr to reshape the data to the format that ggplot2 expects.
rc2 <- rest_change %>% gather(variable, value, -category)
rc2
# Now we can plot it.
# The category that we added goes along the x-axis, the values go along the y-axis.
# We want a bar chart and the value column contains absolute values, so no summation
# necessary, hence we use 'identity'.
# facet_grid() gives three miniplots within the image for each of the variables.
ggplot2(rc2, aes(x=category, y=value, facet=variable)) +
geom_bar(stat='identity') +
facet_grid(~variable)
You have to melt your data:
library(reshape2) # or library(data.table)
rest_change$rowN <- 1:nrow(rest_change)
rest_change <- melt(rest_change, id.var = "rowN")
ggplot(rest_change,aes(x = rowN, y = value)) + geom_bar(stat = "identity") + facet_wrap(~ variable)
I am fairly new to R and am attempting to plot two time series lines simultaneously (using different colors, of course) making use of ggplot2.
I have 2 data frames. the first one has 'Percent change for X' and 'Date' columns. The second one has 'Percent change for Y' and 'Date' columns as well, i.e., both have a 'Date' column with the same values whereas the 'Percent Change' columns have different values.
I would like to plot the 'Percent Change' columns against 'Date' (common to both) using ggplot2 on a single plot.
The examples that I found online made use of the same data frame with different variables to achieve this, I have not been able to find anything that makes use of 2 data frames to get to the plot. I do not want to bind the two data frames together, I want to keep them separate. Here is the code that I am using:
ggplot(jobsAFAM, aes(x=jobsAFAM$data_date, y=jobsAFAM$Percent.Change)) + geom_line() +
xlab("") + ylab("")
But this code produces only one line and I would like to add another line on top of it.
Any help would be much appreciated.
TIA.
ggplot allows you to have multiple layers, and that is what you should take advantage of here.
In the plot created below, you can see that there are two geom_line statements hitting each of your datasets and plotting them together on one plot. You can extend that logic if you wish to add any other dataset, plot, or even features of the chart such as the axis labels.
library(ggplot2)
jobsAFAM1 <- data.frame(
data_date = runif(5,1,100),
Percent.Change = runif(5,1,100)
)
jobsAFAM2 <- data.frame(
data_date = runif(5,1,100),
Percent.Change = runif(5,1,100)
)
ggplot() +
geom_line(data = jobsAFAM1, aes(x = data_date, y = Percent.Change), color = "red") +
geom_line(data = jobsAFAM2, aes(x = data_date, y = Percent.Change), color = "blue") +
xlab('data_date') +
ylab('percent.change')
If both data frames have the same column names then you should add one data frame inside ggplot() call and also name x and y values inside aes() of ggplot() call. Then add first geom_line() for the first line and add second geom_line() call with data=df2 (where df2 is your second data frame). If you need to have lines in different colors then add color= and name for eahc line inside aes() of each geom_line().
df1<-data.frame(x=1:10,y=rnorm(10))
df2<-data.frame(x=1:10,y=rnorm(10))
ggplot(df1,aes(x,y))+geom_line(aes(color="First line"))+
geom_line(data=df2,aes(color="Second line"))+
labs(color="Legend text")
I prefer using the ggfortify library. It is a ggplot2 wrapper that recognizes the type of object inside the autoplot function and chooses the best ggplot methods to plot. At least I don't have to remember the syntax of ggplot2.
library(ggfortify)
ts1 <- 1:100
ts2 <- 1:100*0.8
autoplot(ts( cbind(ts1, ts2) , start = c(2010,5), frequency = 12 ),
facets = FALSE)
I know this is old but it is still relevant. You can take advantage of reshape2::melt to change the dataframe into a more friendly structure for ggplot2.
Advantages:
allows you plot any number of lines
each line with a different color
adds a legend for each line
with only one call to ggplot/geom_line
Disadvantage:
an extra package(reshape2) required
melting is not so intuitive at first
For example:
jobsAFAM1 <- data.frame(
data_date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 100),
Percent.Change = runif(5,1,100)
)
jobsAFAM2 <- data.frame(
data_date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 100),
Percent.Change = runif(5,1,100)
)
jobsAFAM <- merge(jobsAFAM1, jobsAFAM2, by="data_date")
jobsAFAMMelted <- reshape2::melt(jobsAFAM, id.var='data_date')
ggplot(jobsAFAMMelted, aes(x=data_date, y=value, col=variable)) + geom_line()
This is old, just update new tidyverse workflow not mentioned above.
library(tidyverse)
jobsAFAM1 <- tibble(
date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 5),
Percent.Change = runif(5, 0,1)
) %>%
mutate(serial='jobsAFAM1')
jobsAFAM2 <- tibble(
date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 5),
Percent.Change = runif(5, 0,1)
) %>%
mutate(serial='jobsAFAM2')
jobsAFAM <- bind_rows(jobsAFAM1, jobsAFAM2)
ggplot(jobsAFAM, aes(x=date, y=Percent.Change, col=serial)) + geom_line()
#Chris Njuguna
tidyr::gather() is the one in tidyverse workflow to turn wide dataframe to long tidy layout, then ggplot could plot multiple serials.
An alternative is to bind the dataframes, and assign them the type of variable they represent. This will let you use the full dataset in a tidier way
library(ggplot2)
library(dplyr)
df1 <- data.frame(dates = 1:10,Variable = rnorm(mean = 0.5,10))
df2 <- data.frame(dates = 1:10,Variable = rnorm(mean = -0.5,10))
df3 <- df1 %>%
mutate(Type = 'a') %>%
bind_rows(df2 %>%
mutate(Type = 'b'))
ggplot(df3,aes(y = Variable,x = dates,color = Type)) +
geom_line()