Can't plot circular points in R using ggplot2 - r

After experimenting with different point sizes and shapes when plotting with ggplot2, I found that I was no longer able to plot circular points. These simple examples illustrate the problem:
# Plot 1 - square points (symbol #15) appear correctly
#
df = data.frame(x = c(1, 2, 3), y = c(4, 5, 6))
g1 <- ggplot(df, aes(x = x, y = y))
g1 <- g1 + geom_point(size = 3, shape = 15)
g1
Plot 1 output:
# Plot 2 - circular points (symbol #16) appear as diamonds
#
df = data.frame(x = c(1, 2, 3), y = c(4, 5, 6))
g1 <- ggplot(df, aes(x = x, y = y))
g1 <- g1 + geom_point(size = 3, shape = 16)
g1
Plot 2 output:
# Plot 3 - triangular points (symbol #17) appear correctly
#
df = data.frame(x = c(1, 2, 3), y = c(4, 5, 6))
g1 <- ggplot(df, aes(x = x, y = y))
g1 <- g1 + geom_point(size = 3, shape = 17)
g1
Plot 3 output:
# Plot 4 - diamond points (symbol #18) appear correctly
#
df = data.frame(x = c(1, 2, 3), y = c(4, 5, 6))
g1 <- ggplot(df, aes(x = x, y = y))
g1 <- g1 + geom_point(size = 3, shape = 18)
g1
Plot 4 output:
What do I have to do to plot circular points again?
(I'm running R 3.1.3 and RStudio 0.98.1103 in Windows 7.)

It looks like it has to do with the limited resolution of the RStudioGD() graphics device. It becomes a non-issue by avoiding the RStudio interface:
g1 <- ggplot(df, aes(x = x, y = y))
g1 <- g1 + geom_point(size = 3)
g1
(from RStudio interface via save image)
ggsave(g1, filename = "image.png")
ggsave gives you more finely-tuned control over graphics parameters, including the height/width, dpi (for raster images, eg. png), and file format. See the ?ggsave documentation for details.
Or alternatively, bump the geom_point up to size = 4.

Related

ggplot from two tibbles; scatterplot with contours in background

I have two tibbles -
tbl1 contains real data : X, Y and choice.
tbl2 is synthetic tibble to calculate contours of predicted choice P.
library(tidyverse)
# tibble1
X <- c(1, 3, 5)
Y <- c(1, 5, 3)
choice <- c(0, 1, 1)
tbl1 <- tibble(X,Y,choice)
# tibble2
X <- seq(0, 5, 0.1)
Y <- seq(0, 5, 0.1)
tbl2 <- crossing(X,Y)
tbl2 <- tbl2 %>%
mutate(V = (X + Y - 4)/2,
P = 1/(1+exp(-V)))
I wish to create a single ggplot with
scatterplot X vs Y from tbl1 (with color = choice)
filled contours of P from tbl2 in the background
Thanks
Perhaps this?
library(ggplot2)
ggplot(tbl2, aes(X, Y)) +
geom_contour_filled(aes(z = P), alpha = 0.3) +
geom_point(aes(color = factor(choice)), size = 5, data = tbl1) +
guides(fill = guide_none()) +
labs(color = "Choice")

How to combine ggplot and plotly graph?

I prepare a data.frame as follow;
#create dataframe
df <-data.frame(x = c(rnorm(300, 3, 2.5), rnorm(150, 7, 2)), # create random data
y = c(rnorm(300, 6, 2.5), rnorm(150, 2, 2)),
z = c(rnorm(300, 6, 2.5), rnorm(150, 2, 2)),
group = c(rep('A', 300), rep('B', 150))) # add two groups
The relationship between y and x is like below, when showing by ggplot2;
#for y-x correlation by group with fit curve
gg <- ggplot(df, aes(x=x, y=y)) +
stat_density_2d(geom = "polygon", aes(alpha = ..level..,fill=group))+
geom_smooth(method = 'loess')
print(gg)
Then, I created plot_ly 3D figure as follows;
#plot_ly 3D plot
s = interp(x = df$x, y = df$y, z = df$z,duplicate = "mean") # prepare for plot_ly plot
p <- plot_ly(x = s$x, y = s$y, z = s$z,colorscale = 'Jet')%>% # plot_ly
add_surface()
, which created a graph as below;
Then, here is the question.
I would like to add the first ggplot2 figure at the bottom of the second plot_ly figure, like as below;
Is there any way (function or package) to accomplish this with R?

Plot a density differential semantic dataset

I'm coming here because after hours of research and failed trials, i dont know what to do next.
I've a database (opened via dyplr with the open_excel command) that looks like the one below (but more complexe with more variables) :
> dput(open)
structure(list(Subject = c(1, 2, 3, 4, 5), `Happy - Before` = c(4,
4, 2, 1, 7), `Courageous - Before` = c(5, 2, 1, 3, 4), `Strange - Before` = c(1,
2, 1, 4, 6), `Happy - After` = c(4, 2, 6, 2, 2), `Courageous - After` = c(7,
1, 5, 1, 2), `Strange - After` = c(3, 7, 4, 5, 4)), row.names = c(NA,
-5L), class = c("tbl_df", "tbl", "data.frame"))
# A tibble: 5 x 7
Subject `Happy - Before` `Courageous - B… `Strange - Befo… `Happy - After`
<dbl> <dbl> <dbl> <dbl> <dbl>
1 1 4 5 1 4
2 2 4 2 2 2
3 3 2 1 1 6
4 4 1 3 4 2
5 5 7 4 6 2
# … with 2 more variables: `Courageous - After` <dbl>, `Strange - After` <dbl>
My goal here is to plot a density graph with some specificity :
Density of scores obtained by all the subjects for each ability trait on a scale from 1 to 7
As you can see on my (awful) graph, i'm trying to display the responses of all my subjects on a scale from 1 to 7 (x axis) via a density plot, but for each trait i have (y - axis), and thus, with a separation from responses made before [a test] and after a test. And i need to get the same kind of legend (courageous shown to the left, not courageous shown to the right). The more a participant is close to 7 when he answer to the scale, the more he is [happy, courageous, depressed, anxious....] and the more he get close to 1, the more he is [not happy, not courageous, not depressed...]
I tried my best (using ggplot2 templates, trying to melt things and all but i fairly new to R and language programming :/)
All my variables have thos kind of name : [trait1]_before, [trait2]_before, [trait1]_After, [trait2]_After
I hope this post is clear. If not, i will be glad to add informations !
Thank you everyone (sorry for my pooor english)
A density plot assumes a continuous variable along the x axis, whereas your example only goes from 1 to 7. This means you can plot the density where you will have tails that go past 0 and 7 or force a cut-off at those values.
data <- structure(list(Subject = c(1, 2, 3, 4, 5),
`Happy - Before` = c(4, 4, 2, 1, 7),
`Courageous - Before` = c(5, 2, 1, 3, 4),
`Strange - Before` = c(1, 2, 1, 4, 6),
`Happy - After` = c(4, 2, 6, 2, 2),
`Courageous - After` = c(7, 1, 5, 1, 2),
`Strange - After` = c(3, 7, 4, 5, 4)),
row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"))
library(tidyverse)
library(ggplot2)
library(ggridges)
library(grid)
library(gtable)
dataPivot <- data %>%
pivot_longer(-Subject, names_to = "measure", values_to = "score") %>%
mutate(status = sub(".* - ", "", measure),
feature = sub(" - .*", "", measure),
featureOpposite = paste('Not', feature)) %>%
mutate_if(is.character, as.factor)
If you want to not truncate the plot:
# Create the first plot with the axis on the left
p1 <- ggplot(dataTest, aes(x = score, y = feature)) +
geom_density_ridges2(aes(fill = status), scale = 0.7, alpha = .3) +
scale_x_continuous(breaks = c(1, 7)) +
labs(y = NULL) +
theme_ridges() +
theme(legend.position="bottom")
# Create a second plot with the legend on the right
p2 <- ggplot(dataTest, aes(x = score, y = featureOpposite)) +
geom_density_ridges2(aes(fill = status), scale = 0.7, alpha = .3) +
scale_y_discrete(position = "right") +
theme_ridges() +
theme(legend.position="bottom")
# Convert both plots to gtables
g1 <- ggplot_gtable(ggplot_build(p1))
g2 <- ggplot_gtable(ggplot_build(p2))
# Add an empty column to the left side of the first plot to make room for the right
# axis
g1 <- gtable_add_cols(g1, widths = unit(0.2, "null"), pos = -1)
# overlap the panel of the 2nd plot on that of the 1st plot
pp <- c(subset(g1$layout, name == "axis-r", se = t:r))
# Add the y-axis from the second plot
g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name == "axis-r")]], pp$t, pp$r,
pp$b, pp$r)
grid.draw(g)
If you want to truncate the ends:
# Here we are just adding in a height variable, changing stat to density and adding
# trim = T
p1 <- ggplot(dataTest, aes(x = score, y = feature, height = ..density..)) +
geom_density_ridges2(aes(fill = status), scale = 0.7, alpha = .3, stat = "density",
trim = TRUE) +
scale_x_continuous(breaks = c(1, 7)) +
labs(y = NULL) +
theme_ridges() +
theme(legend.position="bottom")
p2 <- ggplot(dataTest, aes(x = score, y = featureOpposite, height = ..density..)) +
geom_density_ridges2(aes(fill = status), scale = 0.7, alpha = .3, stat = "density",
trim = TRUE) +
scale_y_discrete(position = "right") +
theme_ridges() +
theme(legend.position="bottom")
g1 <- ggplot_gtable(ggplot_build(p1))
g2 <- ggplot_gtable(ggplot_build(p2))
g1 <- gtable_add_cols(g1, widths = unit(0.2, "null"), pos = -1)
## overlap the panel of the 2nd plot on that of the 1st plot
pp <- c(subset(g1$layout, name=="axis-r", se=t:r))
g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name=="axis-r")]], pp$t, pp$r,
pp$b, pp$r)
grid.draw(g)
I wonder (as also hinted by #Amanda) whether a density plot is appropriate for this kind of data, but leaving this to the side, here's a shorter version that does not attempt to massage the data like #Amanda.
You can play around with the bw for different bandwidth selection methods (the default, nrd0 is generally not recommended for non-Gaussian distributions as it tends to over-smooth).
library(tidyverse)
open_long <- open %>%
pivot_longer(-Subject, names_to = c("state", "time"), names_pattern = "([A-Za-z]+) - ([A-Za-z]+)")
ggplot(open_long, aes(x = value, fill = time)) +
geom_density(alpha = 0.5, bw = "SJ") +
facet_wrap(~state, ncol = 1) +
theme_bw()
Created on 2019-12-20 by the reprex package (v0.3.0)

Recursive indexing error with facet wrap

I have two graphics side-by-side using facet_wrap and want to do the following things:
draw a square, but a different square in each facet
draw a vertical line, but a vertical line in a different location in each facet
I used this link to accomplish #1, but I can't do #2 in combination with that
ggplot2 - create different geom_path objects in facets
I created the following data frames
square1 = data.frame(x=c(.....),y=c(.....),z=a)
square2 = data.frame(x=c(.....),y=c(.....),z=b)
df1 = rbind(square1,square2) # 10*3 data frame that defines the dimensions of the squares to draw with z taking value of a or b
df2 = data.frame(x=c(..),z=c(a,b)) # 2*2 data frame with z taking value of a or b
The below code sets up the facets and all works fine:
RE <- ggplot(data, aes())
RE <- RE + geom_point(aes())
RE <- RE + xlab() + ylab() + ggtitle()
RE <- RE + coord_cartesian()
RE <- RE + scale_colour_brewer()
RE <- RE + theme_bw()
RE <- facet_wrap(~ v1 + v2, ncol=2)
But running this code results in the following error:
RE <- RE + geom_path(aes(x = x, y = y), data = df1)
RE <- RE + geom_vline(aes(xintercept = x), data = df2)
Error in panel$x_scales[[this_panel$SCALE_X]] : recursive indexing
failed at level 4
Note that I can run one or the other lines of code but not both.
You have not provided any data so I have created some data following the pattern you provided in your earlier post. Note that the data frame contains x and y coordinates for the points and the paths; a variable facet to tell ggplot in which panel to draw the points and paths; and a variable vline which gives the location of the vertical lines (in the v1 panel, the vline intercept is at x=2; in the v2 panel, the vline intercept is at x=3).
library(ggplot2)
square1 <- data.frame(x = c(1, 5, 5, 1, 1),
y = c(1, 1, 5, 5, 1),
facet = "v1",
vline = 2)
square2 <- data.frame(x = c(2, 4, 4, 2, 2),
y = c(2, 2, 4, 4, 2),
facet = "v2",
vline = 3)
df1 = rbind(square1,square2)
df1
ggplot(df1, aes(x, y)) +
geom_point(colour = "red", size = 5) +
geom_path(colour = "red", size = 2) +
geom_vline(aes(xintercept = vline),colour = "blue", size = 2) +
theme_bw() +
facet_wrap(~ facet, ncol=2)

How to specify size for geom_point and geom_line separately and get separate legends in ggplot2

I'm trying to plot igraph network with ggplot2. I use geom_point() for the vertex and geom_line() for the edges. The point size and line width in ggplot2 are both specified by size. When I specified them separately, I hope to get two separate legends but they turned out to be merged. Below is an example.
# an example graph
df <- data.frame(from=letters[c(1, 1, 2:4, 4)], to=letters[c(2, 3, 5:7, 1)])
g <- graph.data.frame(df, directed=FALSE)
Vname <- V(g)$name
set.seed(100)
V(g)$varVsize <- rnorm(length(Vname))
E(g)$varEwidth <- rnorm(nrow(df))
E(g)$varEcol <- rnorm(nrow(df), 1, 1)
Vcord <- layout.fruchterman.reingold(g) # get coordinates for the Vertex
rownames(Vcord) <- V(g)$name
# 2-column edge list
el <- get.edgelist(g)
el_df <- data.frame(as.data.frame(el), Ewidth=E(g)$varEwidth, Ecol=E(g)$varEcol)
# assigning edge id so that it can be used as group
el_df$id <- 1:nrow(el_df)
## now g_df have each node in the edgelist as a row: first nodesFrom (id=1:145), then nodesTo (id=146:290, i.e.)
el_dfm <- melt(el_df, id=3:5)
xy_s <- data.frame(value = rownames(Vcord),
Vsize=V(g)$varVsize, # add Vetex attribues here: affects size and color
x = Vcord[, 1],
y = Vcord[, 2])
g_df2 <- merge(el_dfm, xy_s, by = "value")
# fig 1
ggplot(g_df2, aes(x, y)) +
geom_point(data=g_df2, aes(x, y, size=Vsize), alpha=0.4) +
geom_line(aes(color=Ecol, group = id)) +
geom_text(size = 4, aes(label = value), colour='blue')
# fig 2: Vsize and Ewidth legend are merged: transparency in geom_line is used so it will not overlap geom_point
ggplot(g_df2, aes(x, y)) +
geom_point(data=g_df2, aes(x, y, size=Vsize), alpha=0.4) +
geom_line(aes(color=Ecol, group = id, size=Ewidth), alpha=0.3) +
geom_text(size = 4, aes(label = value), colour='blue')

Resources