How to plot only one column in ggplot? - r

Given this simple data I want to plot the equivalent of base
plot(dat$value)
but with ggplot.
dat= structure(list(name = c("Cord", "Cord",
"amo", "amo",
"amo", "ramo"),
value = c(7, 0.7, 9,
0.9, 0.8, 0.7)), row.names = c(NA,
6L), class = "data.frame")
I tried:
> ggplot(data = dat) + geom_point(aes(x = value, colour = name))
Error in `check_required_aesthetics()`:
! geom_point requires the following missing aesthetics: y
I need to plot "count" on y axis vs value on x axis

You could create a row index using tibble::rownames_to_column, then use that to plot along the x-axis, so that you get a similar result to plot(dat$value).
library(tidyverse)
dat %>%
rownames_to_column("ind") %>%
ggplot(aes(x = ind, y = value, color = name)) +
geom_point(size = 3) +
theme_bw()
Output
Or you can put the function directly into ggplot:
ggplot(dat, aes(
x = rownames_to_column(dat)$rowname,
y = value,
color = name
)) +
geom_point(size = 3) +
theme_bw()
Or another option is to use row.names:
ggplot(dat, aes(x = as.numeric(row.names(dat)), y = value, colour = name)) +
geom_point()

Base R plot(dat$value) has an implicit x equal to seq_along(dat$value).
Use x = seq_along(value) and y = value.
dat <- structure(list(name = c("Cord", "Cord",
"amo", "amo",
"amo", "ramo"),
value = c(7, 0.7, 9,
0.9, 0.8, 0.7)),
row.names = c(NA, 6L),
class = "data.frame")
library(ggplot2)
ggplot(dat, aes(x = seq_along(value), y = value, color = name)) +
geom_point()
Created on 2022-03-01 by the reprex package (v2.0.1)

Related

How to write point values to a lineplot in R?

I have a dataframe of single column with multiple values. I was using basic rplot function like plot() and points(). I successfully plotted the lineplot but I was unable to write point values from the dataframe onto the plot field. Is there anyway to add data values onto the plot?
Below is the following code for test
> x = data.frame(A = rnorm(10))
> plot(x$A, type = "o", pch = 20)**
Sorry, I made an edit to make my question clearer.
Here below is the example plot for 10 random numbers
Plot lines, then add text:
#data
set.seed(1); x = data.frame(A = rnorm(10))
#base plot
plot(x$A, type = "o", pch = 20, ylim = range(x$A * 1.3))
text(x = seq_along(x$A), y = x$A + 0.3, labels = round(x$A, 2), srt = 90)
Or using ggplot with ggrepel for pretty labels:
#ggplot
library(ggplot2)
library(ggrepel) # pretty labels, avoid overlap:
ggplot(cbind(x = seq_along(x$A), x),
aes(x = x, y = A, label = round(A, 2))) +
geom_line() +
geom_point() +
geom_label_repel()
#geom_text_repel()
Probably this is more than what you are asking, but you can add labels to the values you have in your line plot using ggplot:
library(ggplot2)
x = data.frame(A = rnorm(10),
pos = runif(10, 0.1, 0.7))
ggplot(x) +
geom_point(aes(x = A),
y = 0) +
geom_line(aes(x = A),
y = 0) +
geom_segment(aes(x = A,
xend = A,
y = 0,
yend = pos),
linetype = 2) +
geom_label(aes(x = A,
y = pos,
label = round(A, 2)),
size = 3) +
scale_y_continuous(name = "",
limits = c(0, 0.8)) +
guides(y = "none") +
theme_bw()
You could make a base R "type b" equivalent.
The OP hasn't specified that every y value should be set to zero.
library(ggh4x)
#> Loading required package: ggplot2
set.seed(1)
x = data.frame(A = rnorm(10))
ggplot(x, aes(1:10, A)) +
geom_pointpath(shape = NA) +
geom_text(aes(label = round(A,2))) +
labs(x= "Index")
Created on 2022-05-27 by the reprex package (v2.0.1)

ggplot piechart label freq instead of percent?

Hi supposed I have the following pie info.
df=structure(list(Var1 = c("a", "b"), Freq = c(306L, 1064L), per = c(0.223357664233577,
0.776642335766423)), row.names = c(NA, -2L), class = "data.frame")
and I plot this pie chart with direction -1
ggplot(data = df,
aes(x = "", y = per, fill = Var1)) +
geom_col() +
geom_text(aes(label = scales::percent(per, accuracy = 1)),
position = position_stack(vjust = 0.5),
color = "grey20", size = pietext ) +
coord_polar(theta = "y", direction =-1 ) +
theme_void ()
However what I would like is to label with with the frequency rather than the percentage.
Var1 Freq per
1 a 306 0.2233577
2 b 1064 0.7766423
Is this possible with this method? I tried replacing per with Freq but that just gave some really strange text.
thank you.
aes(label = Freq) is the way to go:
ggplot(data = df,
aes(x = "", y = per, fill = Var1)) +
geom_col() +
geom_text(aes(label = Freq),
position = position_stack(vjust = 0.5),
color = "grey20", size=12) +
coord_polar(theta = "y", direction =-1) +
theme_void ()
Just change geom_text(aes(label =Freq)
ggplot(data = df, aes(x = "", y = per, fill = Var1)) +
geom_col() +
geom_text(aes(label =Freq),
position = position_stack(vjust = 0.5),
color = "black", size = 10 ) +
labs( x="", y="", fill="")+
scale_fill_manual(values=c("#4E79A7", "#fc7d0b"))+
coord_polar(theta = "y", direction =-1 ) +
theme_no_axes()
Plot:
or something that is better than a pie chart
Sample code:
library(waffle)
library(ggthemes)
vals <- c(306,1064)
val_names <- sprintf("%s (%s)", c("a","b"), label=vals)
names(vals) <- val_names
waffle::waffle(vals) +
ggthemes::scale_fill_tableau(name=NULL)
Plot:
Sample code:
df=structure(list(Var1 = c("a", "b"), Freq = c(306L, 1064L), per = c(0.223357664233577, 0.776642335766423)), row.names = c(NA, -2L), class = "data.frame")

Combining geom_text with substitute doesn't work

I have the following dataset
structure(list(X = c(9.8186734, 19.6373468, 29.4560202, 39.2746936,
49.093367, 58.9120404, 68.7307138, 78.5493872, 88.3680606, 98.186734
), Y = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), radii = c(530.595715856625,
530.595715856625, 524.270569515141, 520.785212389348, 524.423046929159,
524.777454042683, 523.089321742221, 522.852371975715, 523.124870390148,
522.612174462367), slope = c(-21.796356958782, -21.796356958782,
-21.796356958782, -21.796356958782, -21.796356958782, -21.796356958782,
-21.796356958782, -21.796356958782, -21.796356958782, -21.796356958782
)), row.names = c(NA, -10L), class = c("data.table", "data.frame"
), .internal.selfref = <pointer: 0x7f989f011ce0>, sorted = "Y")
and I am simply trying to print slope as a text to the figure as
str_slope <- c(substitute("Slope = "~sp~mu*"m/s", list(sp = sprintf("%2.1f", dt[!duplicated(slope), slope]))))
d_text <- data.table(x=2000, y=500, label = str_slope)
ggplot(dt, aes(x = X, y=radii)) +
geom_point()+
geom_smooth(method = "lm", level = 0.9999, se = TRUE)+
scale_colour_manual(values = getPalette) +
labs(x = "time (s)", y = expression("radius ["*mu*"m]"), color = "Speed [µm/s]") +
geom_text(data = d_text, aes(x = x, y = y, label = label))+
theme_default(legend.position = "none")
but I get something like this
Why is the text in str_slope not evaluated as an expression? How can I force ggplot to interpret it as an expression, so that the text will look like
For this type of plot annotation, you should use annotate(geom="text"...) rather than geom_text(). For how to generate the expression, you can use the parse=TRUE argument within annotate().
I think we're missing all your plot data, so here's an example with mtcars that incorporates the contents of str_slope in your example.
str_slope <- c(substitute("Slope = "~sp~mu*"m/s", list(sp = sprintf("%2.1f", dt[!duplicated(slope), slope]))))
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
p + annotate(
"text", x=4, y=25,
label= str_slope, parse=TRUE)
For your information, geom_text() is designed to be used wherein one or more aesthetics are mapped to a data frame. If you have only one line of text you want to appear on the plot, you should use annotate(geom="text"...), which is used when you do not want to map any aesthetics to a data frame.

ggplot custom legend instead of default

I've searched and tried a bunch of suggestions to be able to display a custom legend instead of the default one in a grouped scatter ggplot. I've tried this and this and following this among others.
For instance, let's say I have a df like this one:
df = data.frame(id = c("A", "A", "B", "C", "C", "C"),
value = c(1,2,1,2,3,4),
ref = c(1.5, 1.5, 1, 2,2,2),
min = c(0.5, 0.5, 1,2,2,2))
and I want to display the values of each id as round dots, but also put the reference values and minimum values for each id as a differently shaped dot, as follows:
p = ggplot(data = df) +
geom_point(aes(x = id, y = value, color = factor(id)), shape = 19, size = 6) +
geom_point(aes(x = id, y = ref, color = factor(id)), shape = 0, size = 8) +
geom_point(aes(x = id, y = min, color = factor(id)), shape = 2, size = 8) +
xlab("") +
ylab("Value")
#print(p)
Now all is fine, but my legend doesn't add anything to the interpretation of the plot, as the X axis and colors are enough to understand it. I know I can remove the legend via theme(legend.position = "none").
Instead, I would like to have a legend of what the actual shapes of each dot represent (e.g., filled round dot = value, triangle = min, square = ref).
Among trying to manually set the scale values via scale_fill_manual and something along those lines
override.shape = shapes$shape
override.linetype = shapes$pch
guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype)))...
....
I've also tried making a secondary plot, but not display it, using something suggested in one of the links pasted above:
shapes = data.frame(shape = c("value", "reference", "minimum"), pch = c(19,0,2), col = c("gray", "gray", "gray"))
p2 = ggplot(shapes, aes(shape, pch)) + geom_point()
#print(p2)
g_legend <- function(a.gplot){
tmp <- ggplot_gtable(ggplot_build(a.gplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- g_legend(p2)
library(gridExtra)
pp <- arrangeGrob(p1 ,legend,
widths=c(5/4, 1/4),
ncol = 2)
but then I get the error:
> legend <- g_legend(p2)
Error in tmp$grobs[[leg]] :
attempt to select less than one element in get1index
for which I did not find a working solution.. so yeah.. any suggestion on how I could only show a legend related to the different dot shapes would be welcome.
Thank you
You can manually build a shape legend using scale_shape_manual:
library(ggplot2)
ggplot(data = df) +
geom_point(aes(x = id, y = value, color = factor(id), shape = 'value'), size = 6) +
geom_point(aes(x = id, y = ref, color = factor(id), shape = 'ref'), size = 8) +
geom_point(aes(x = id, y = min, color = factor(id), shape = 'min'), size = 8) +
scale_shape_manual(values = c('value' = 19, 'ref' = 0, 'min' = 2)) +
xlab("") +
ylab("Value")
Created on 2020-04-15 by the reprex package (v0.3.0)
But a better way to do this would be to reshape the df to a long format, and map each aes to a variable:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(-id) %>%
ggplot() +
geom_point(aes(x = id, y = value, color = factor(id), shape = name, size = name)) +
scale_shape_manual(values = c('value' = 19, 'ref' = 0, 'min' = 2)) +
scale_size_manual(values = c('value' = 6, 'ref' = 8, 'min' = 8)) +
xlab("") +
ylab("Value")
Created on 2020-04-15 by the reprex package (v0.3.0)
To remove the legend for the color use guide_none():
library(tidyr)
library(ggplot2)
df %>%
pivot_longer(-id) %>%
ggplot() +
geom_point(aes(x = id, y = value, color = factor(id), shape = name, size = name)) +
scale_shape_manual(values = c('value' = 19, 'ref' = 0, 'min' = 2)) +
scale_size_manual(values = c('value' = 6, 'ref' = 8, 'min' = 8)) +
guides(color = guide_none()) +
xlab("") +
ylab("Value")
Created on 2020-04-16 by the reprex package (v0.3.0)
Data:
df = data.frame(id = c("A", "A", "B", "C", "C", "C"),
value = c(1,2,1,2,3,4),
ref = c(1.5, 1.5, 1, 2,2,2),
min = c(0.5, 0.5, 1,2,2,2))
You can tidy your data first using tidyr, and then map the aes shape to the new variable
library(tidyr)
df2 <- pivot_longer(df, -id)
ggplot(data = df2) +
geom_point(aes(x = id, y = value, shape = name), size = 6) +
xlab("") +
ylab("Value")

connecting points

I have the following plot
require(ggplot2)
dtf <- structure(list(Variance = c(5.213, 1.377, 0.858, 0.613, 0.412, 0.229, 0.139, 0.094, 0.064), Component = structure(1:9, .Label = c("PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9"), class = "factor")), .Names = c("Variance", "Component"), row.names = c(NA, -9L), class = "data.frame")
ggplot(dtf, aes(x = Component, y = Variance)) +
geom_point()
I would simply like to connect the dots with straight lines. I tried +geom_line() but that generated an error
Your x values are discrete (factor) and geom_line() each unique x value perceive as separate group and tries to connect points only inside this group. Setting group=1 in aes() ensures that all values are treated as one group.
ggplot(dtf, aes(x = Component, y = Variance,group=1)) +
geom_point()+geom_line()
This would plot the points with x as the integer values of the factor categories:
ggplot(dtf, aes(x = as.numeric(Component), y = Variance)) +
geom_point() + geom_line()
You can put back in the category labels with:
ggplot(dtf, aes(x = as.numeric(Component), y = Variance)) +
geom_point() +geom_line() + scale_x_discrete(labels=dtf$Component)

Resources