Heatmap representing the number of fixations - r

I am working in a heat map for some eye tracking data. I figured out how to do the heat map and it is very compelling. This is the code:
ggplot(eyematrixCorrectMatchControl, aes(x = CURRENT_FIX_X, y =CURRENT_FIX_Y)) +
annotation_raster(image, -Inf, Inf, -Inf, Inf, interpolate = TRUE) +
stat_density2d(data= eyematrixCorrectMatchControl, aes(x = CURRENT_FIX_X, y =CURRENT_FIX_Y, fill = ..level.., alpha = ..level..), size= 10, bins= 50, geom='polygon') +
theme_bw() +scale_fill_gradient(low = "blue", high = "red") +
scale_alpha_continuous(range=c(0.01,0.25) , guide = FALSE) +
coord_cartesian(xlim= c(0,1024), ylim= c(0,768))+
scale_y_reverse() +
theme(axis.line=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.ticks=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank())
With this code, I obtain this image:
However, I don't understand some things. I thought that this code would give me a graph the number of fixations in a specific area (the more fixation the redder the area is). However, looking at the legend I am not sure what this graph shows. How can I obtain a graph showing the number of fixations? I would also like that the legend reflects the number of fixations, so the redder the more fixations. Any idea??
I edit to add some extra information that might be useful. In my original dataframe I also have a variable called fixation_index. I think that I have to include this variable somewhere, but not really sure.
Thanks!

Heatmap.2 offers a histogram option that correlates color with the density count. It looks like this.

Related

How to add labels and points to each geom_line in ggplot2?

I have a dataframe called (casos_obitos) that looks something like this:
EPI_WEEK CASES DEATHS
SE 51 1053 19
SE 52 1384 21
SE 53 1892 25
SE 01/21 1806 43
I'm making a plot with ggplot that places both cases and deaths in two different geom_lines. This is my code:
scl = 10
ggplot(data = casos_obitos, aes(x = EPI_WEEK, y = CASES, fill = CASES, group =1))+
scale_y_continuous(limits = c(0, max(casos_obitos$CASES)+10), expand = expansion(mult = c(0, .1)),
sec.axis = sec_axis(~./scl, name = "Nº de Óbitos"))+
geom_line(aes(x = SEM_EPI, y = CASES, color = "CASES"), size = 1)+
geom_line(aes(x = SEM_EPI, y = DEATHS*scl, color = "DEATHS"), size = 1) +
geom_text(aes(label= CASES), hjust= 0.5, vjust = -2, size= 2.0, color= "black") +
labs(x = "Semana Epidemiológica", y = "Nº de Casos") +
scale_colour_manual(" ", values=c("CASES" = "blue", "DEATHS" = "red"))+
theme_minimal(base_size = 10) +
theme(legend.position = "bottom", axis.line = element_line(colour = "black"),
axis.text.x=element_text(angle = 90, vjust = 0.5, hjust=1, color="black"),
axis.text.y=element_text(color="black"))
For now, my plot looks like this:
Where the blue line is the cases column and the red one is the deaths column. I need to put labels on the red line but I can't seem to find answers for that. I also wany to put labels in a "nice looking" way so I can understand the numbers and they don't look messy like they're right now.
Thanks!
You should be able to add the following to get labels on the bottom line:
geom_text(aes(y = DEATHS*scl, label= DEATHS), hjust= 0.5, vjust = -2, size= 2.0, color= "black") +
You might also consider reshaping your data into a long format so that the CASES and DEATHS (after scaling) values are combined into the same column, with another column distinguishing which series is related to each value. ggplot2 generally works more smoothly with data in that form -- you would map the color aesthetic to the column specifying which series, and then you'd only need one geom_line and one geom_text to get both series. In this case, with only two series, and one of them scaled, it might not be worth the trouble to switch.
"Nice looking labels" is subjective and a harder problem than it might sound. There are a few options, including:
use a function like ggrepel::geom_text_repel to automatically shift labels from overlapping each other. It works by starting from an initial point and iteratively nudging until the labels have as much separation as you've specified. Many options for adjusting the initial starting position and how the nudging should work.
manually nudge the labels you need to using code, e.g. by adjusting vjust for certain points. You might, for instance, use vjust to make the labels under the line for the points that are lower than neighboring points, by pre-calculating a moving average and comparing values to that.
manually nudge the points afterward, e.g. by using officer/svg to output to a vector file you can edit in powerpoint, for instance.
avoid persistent labels altogether by shifting to an interactive option like ggplotly and see the labels upon hover instead of all the time.
You might also take a look at functions like scales::comma to control how the labels themselves appear. I'm anticipating that your Deaths labels will have many digits of decimals but you probably just will want the integer part of that...

coord_map() of ggplot2 ignores plot.background and produces white margins – how to remove them?

Problem
Greetings, I'm trying to plot a map with a dark background using ggplot2 by setting the theme() parameter plot.background to e.g. element_rect(fill = "#000000") but switching from the cartesian coordinate system to a map projection using coord_map() introduces white margins which can only be removed by adjusting the size of the plot to the same ratio as the map area.
How can I remove this margin and apply the fill colour specified using the plot.background parameter to the whole plot regardless of its ratio?
MWE
nz <- map_data("nz")
ggplot(nz, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black") +
coord_map() +
theme_void() +
theme(plot.background = element_rect(fill = "#000000"))
Output
Expected output
Update
After about two hours of trying different approaches and wondering how R plotting and especially ggplot2 can be so incredibly clumsy, I finally found a solution here but it requires another library and additional steps to produce this conceptually elementary adjustment which should really be the default in the first place so there surely must be a native solution… right? 😓
There is a solution with the grid package, which is the package ggplot2 uses to draw the plots. First, I would make the small adjustment to your plotting code by also setting the plot background colour to black:
g <- ggplot(nz, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black") +
coord_map() +
theme_void() +
theme(plot.background = element_rect(fill = "#000000", colour = "#000000"))
Next we convert the g to a gtable and draw it with the grid package:
library(grid)
gt <- ggplotGrob(g)
grid.newpage()
# Draw a black rectangle
grid.draw(rectGrob(gp = gpar(fill = "#000000")))
grid.draw(gt)
The problem is that many coord-functions set a fixed aspect ratio for the plot, which will in turn affect other plot elements that are defined in absolute dimensions.

Creating a density histogram in ggplot2?

I want to create the next histogram density plot with ggplot2. In the "normal" way (base packages) is really easy:
set.seed(46)
vector <- rnorm(500)
breaks <- quantile(vector,seq(0,1,by=0.1))
labels = 1:(length(breaks)-1)
den = density(vector)
hist(df$vector,
breaks=breaks,
col=rainbow(length(breaks)),
probability=TRUE)
lines(den)
With ggplot I have reached this so far:
seg <- cut(vector,breaks,
labels=labels,
include.lowest = TRUE, right = TRUE)
df = data.frame(vector=vector,seg=seg)
ggplot(df) +
geom_histogram(breaks=breaks,
aes(x=vector,
y=..density..,
fill=seg)) +
geom_density(aes(x=vector,
y=..density..))
But the "y" scale has the wrong dimension. I have noted that the next run gets the "y" scale right.
ggplot(df) +
geom_histogram(breaks=breaks,
aes(x=vector,
y=..density..,
fill=seg)) +
geom_density(aes(x=vector,
y=..density..))
I just do not understand it. y=..density.. is there, that should be the height. So why on earth my scale gets modified when I try to fill it?
I do need the colours. I just want a histogram where the breaks and the colours of each block are directionally set according to the default ggplot fill colours.
Manually, I added colors to your percentile bars. See if this works for you.
library(ggplot2)
ggplot(df, aes(x=vector)) +
geom_histogram(breaks=breaks,aes(y=..density..),colour="black",fill=c("red","orange","yellow","lightgreen","green","darkgreen","blue","darkblue","purple","pink")) +
geom_density(aes(y=..density..)) +
scale_x_continuous(breaks=c(-3,-2,-1,0,1,2,3)) +
ylab("Density") + xlab("df$vector") + ggtitle("Histogram of df$vector") +
theme_bw() + theme(plot.title=element_text(size=20),
axis.title.y=element_text(size = 16, vjust=+0.2),
axis.title.x=element_text(size = 16, vjust=-0.2),
axis.text.y=element_text(size = 14),
axis.text.x=element_text(size = 14),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank())
fill=seg results in grouping. You are actually getting a different histogram for each value of seg. If you don't need the colours, you could use this:
ggplot(df) +
geom_histogram(breaks=breaks,aes(x=vector,y=..density..), position="identity") +
geom_density(aes(x=vector,y=..density..))
If you need the colours, it might be easiest to calculate the density values outside of ggplot2.
Or an option with ggpubr
library(ggpubr)
gghistogram(df, x = "vector", add = "mean", rug = TRUE, fill = "seg",
palette = c("#00AFBB", "#E7B800", "#E5A800", "#00BFAB", "#01ADFA",
"#00FABA", "#00BEAF", "#01AEBF", "#00EABA", "#00EABB"), add_density = TRUE)
The confusion regarding interpreting the y-axis might be due to density is plotted rather than count. So, the values on the y-axis are proportions of the total sample, where the sum of the bars is equal to 1.

R: ggplot2: Adding count labels to histogram with density overlay

I have a time-series that I'm examining for data heterogeneity, and wish to explain some important facets of this to some data analysts. I have a density histogram overlayed by a KDE plot (in order to see both plots obviously). However the original data are counts, and I want to place the count values as labels above the histogram bars.
Here is some code:
$tix_hist <- ggplot(tix, aes(x=Tix_Cnt))
+ geom_histogram(aes(y = ..density..), colour="black", fill="orange", binwidth=50)
+ xlab("Bin") + ylab("Density") + geom_density(aes(y = ..density..),fill=NA, colour="blue")
+ scale_x_continuous(breaks=seq(1,1700,by=100))
tix_hist + opts(
title = "Ticket Density To-Date",
plot.title = theme_text(face="bold", size=18),
axis.title.x = theme_text(face="bold", size=16),
axis.title.y = theme_text(face="bold", size=14, angle=90),
axis.text.x = theme_text(face="bold", size=14),
axis.text.y = theme_text(face="bold", size=14)
)
I thought about extrapolating count values using KDE bandwidth, etc, . Is it possible to data frame the numeric output of a ggplot frequency histogram and add this as a 'layer'. I'm not savvy on the layer() function yet, but any ideas would be helpful. Many thanks!
if you want the y-axis to show the bin_count number, at the same time, adding a density curve on this histogram,
you might use geom_histogram() first and record the binwidth value! (this is very important!), next add a layer of geom_density() to show the fitting curve.
if you don't know how to choose the binwidth value, you can just calculate:
my_binwidth = (max(Tix_Cnt)-min(Tix_Cnt))/30;
(this is exactly what geom_histogram does in default.)
The code is given below:
(suppose the binwith value you just calculated is 0.001)
tix_hist <- ggplot(tix, aes(x=Tix_Cnt)) ;
tix_hist<- tix_hist + geom_histogram(aes(y=..count..),colour="blue",fill="white",binwidth=0.001);
tix_hist<- tix_hist + geom_density(aes(y=0.001*..count..),alpha=0.2,fill="#FF6666",adjust=4);
print(tix_hist);

Custom ggplot output (colour, appearence, etc)

I am quite new to ggplot2, so forgive me if this post is too stupid.
I used the following code to plot the data, but I am not able to get the style that I need for publication.
In the output, I need:
a legend. In my data case, there is nothing after opts(legend.position="top") I have no idea why. And I also would like to split the legend into 3 columns like columns=3 in auto.key of lattice
Colorize the bars using grey system (eg, fill=c("white","grey20","grey70"))according to factor pl, but it seems that I cannot change the style with scale_colour_manual
turn around the labels on the x-axis into horizontal.
maybe a y-axis? But,do you think it is necessary?
BTW, I have no idea how to prepare a figure for publication, so, any suggestion is very welcome!
library(ggplot2)
wt<-gl(3,4,108,labels=c("W30","W60","W90"))
pl<-gl(3,12,108,labels=c("P0","P1","P2"))
gp<-gl(3,36,108,labels=c("A","B","C"))
dat<-cbind(A=runif(108),B=runif(108,min=1,max=10),C=runif(108,min=100,max=200),D=runif(108,min=1000,max=1500))
dat.df<-data.frame(wt,pl,gp,dat)
dat.m<-melt(dat.df)
ggplot(dat.m,aes(x=wt,y=value,group=pl,facet=gp,fill=pl))+
stat_summary(fun.y=mean,geom="bar",size=2,position="dodge")+
stat_summary(fun.ymin=function(x)(mean(x)-sd(x)/sqrt(length(x))),geom="errorbar",
fun.ymax=function(x)(mean(x)+sd(x)/sqrt(length(x))),position="dodge")+
facet_grid(variable~facet,scale="free_y")+ opts(legend.position="top")+
scale_colour_manual(values = c("red", "blue", "green"))
Here are some pointers:
To get a horizontal legend, use opts(legend.direction="horizontal")
To change the fill of the bars, you have to specify scale_fill_manual(values=c("white", "grey20", "grey70")). In your example, you have correctly mapped fill to pl. The only missing step is to map the manual scale to fill, rather than colour. Colour generally refers to the outline of the bar, and fill refers to the inside of the bar.
To rotate the angle of axis text, use opts(axis.text.x = theme_text(angle=45)). The default orientation is horizontal, so I use 45 degrees for illustration.
I don't know what you mean by "maybe a y-axis". Perhaps you don't want to display the y-axis, in which case you can suppress it by opts(axis.title.y = theme_blank())
Note that your example was not reproducible, so I had to invent some data. You can make it easier for us to respond if you ensure your example is reproducible:
There is no data for year
There is a reference to trt in your data.frame
You set up data for grp but then refer to it as gp
My code:
dat.df <- data.frame(
gp = gl(3, 36, 108, labels=c("A", "B", "C")),
yr = sample(2000:2010, 108, replace=TRUE),
A=runif(108),
B=runif(108, min=1, max=10),
C=runif(108, min=100, max=200),
D=runif(108, min=1000, max=1500)
)
dat.m <- melt(dat.df)
ggplot(dat.m, aes(x=wt, y=value, group=pl, facet=gp, fill=pl))+
stat_summary(fun.y=mean, geom="bar", size=2, position="dodge")+
stat_summary(fun.ymin=function(x)(mean(x)-sd(x)/sqrt(length(x))), geom="errorbar",
fun.ymax=function(x)(mean(x)+sd(x)/sqrt(length(x))), position="dodge")+#, position="dodge"
facet_grid(variable~facet, scale="free_y")+
scale_fill_manual(values=c("white", "grey20", "grey70")) +
opts(
legend.position="top",
legend.direction="horizontal",
axis.text.x = theme_text(angle=45),
axis.title.y = theme_blank()
)

Resources