input$plot_hover not retaining enough decimal points - r

I am trying to have R shiny print out the sample information when hovering over a data point in a ggplot2 geom_point plot. The axes for my plot have 4 decimal points but if I print plot_hover$x and $y it only returns two decimal points, so the output ends up being the same for every point on the plot. I noticed the examples on the shiny site also only output two decimal points. Is there a way to change this to retain more information in input$plot_hover?

Without a reproduceable example this is tough, so all of these are complete guesses as to what your actual problem is. Here are some stabs in the dark as to how to fix a problem where ggplot is not printing enough digits.
#HubertL: You may be able to control the number of printed digits using
options(digits = 10)
Or use a wrapper around any calculations to specify the number of rounded digits to include in a calculation or output from a function
round(calculation, 10)
Additionally, this could be an issue with the space on the plot axis. You may want to try decreasing the size of the text on the axis within the plot using
plot + theme(axis.text.x = element_text(size = 8))
And you could add angle in there as well to rotate the numbers to validate there is enough space.

Related

TimeSeries: Can't get the type = "o" to work, my data is only plotting horizontal lines for each data point when I need a connected line graph

I am trying to plot a time series graph, but am having issues getting it to be a line graph while showing the decades at the bottom.
My data set has the decades (as factors) next to performance (integer)
If I write
plot(StockPerformance$Decade, StockPerformance$Performance)
I will get a graph that has horizontal lines in it
PLOT PICTURE
adding,
type ="o"
like this:
plot(StockPerformance$Decade, StockPerformance$Performance, type ="o")
doesn't change it....
In R, when you read/create a data frame using read.table (or a variant thereof) or make it using data.frame, it tries to figure out what you have, and treat it appropriately. Specifically, inputs with character vectors (like "1830s" get converted to factors.
Factors are a way to efficiently store character strings - which was a lot more important when R was first created than now. The important thing for you is that characters don't have any order to them unless you put it there, so R automatically makes boxplots out of them. That's why you are seeing lines - they are boxplots with only one point.
To get around this, you need to convert them to numbers for the purpose of plotting. Then, you need to "fix" the axes afterwards. Here's how:
plot(Performance ~ as.numeric(Decade),
data = StockPerformance,
xlab = "Decade", # otherwise we have "as.numeric(Decade)
xaxt = 'n', # removes default axis ticks and labels
pch = 1 # default open circle. Change the number to get other options. 16 and 20 are both closed circles (20 is small, 16 is big)
)
with(StockPerformance, # This just makes it so I don't have to type StockPerformance twice below.
axis(1, at = 1:nlevels(Decade),
value = levels(Decade)
))

Simplifying noisy data for plotting and changing plot dimensions (horizontal)

Data Background: I have a large data frame (50,000 values, 10,000 when removing NAs) for a single chromosome. I am trying to plot a fixation index (Y-range: 0-1)(data$'N:S') across chromosomal positions (X-range: 0-250,000,000)(data$'pos'). I used a program (popoolation 2) to calculate sliding window averages for a window size of 50,000 and a step size of 10,000, resulting in my data. However, on R this is too noisy and it comes out looking like a blob. When I zoom in by changing the x-axis so each tick is 500,000 separation, you can see the trends nicely. I think I can fix this on a large chromosomal stage by increasing the area of the x-axis and finding a way to simplify the data.
Currently I have: All my data plotted, simple mean, StandDevs (color coded)
I am trying to figure out two things.
1 Is there a way to extend the X-axis to stretch out the length of it. I don't want to change the markers on it or what it displays, I want to make the actual length longer. (Example, if I had a graph on a piece of paper that showed an x-Axis of 1-10 on a 2" area, I would want to increase the area to 5", not change the defined limits to say 1-100. so, not xlim function)
2 Simplify the data in some way. I was thinking easiest would be a smoothed or rolling mean across the data. When I use rollmean() or smooth() it separates my data from the x-axis, so it only extends to the 8,000 points and when I plot it doesn't go across the whole chromosomal graph with the rest of my data. Someone mentioned there may be away to instead randomly sample data to simplify it?
2B If I get a trendline to work, can I color code it so that part of it that is 1 or 2 standard deviations above the mean can be a different color if I mute my actual background data and remove its color.
R Code
Image 1-Plotting All Positions
plot(data$'Pos',data$'N:S', ylim=c(0,0.5), col=data$Colour)
Image 3-I tried both
lines(smooth(datatest$`N:S`), type="l", col = "blue", lwd = 1)
and
rolling = rollmean(datatest$N:S, 9)
lines(rolling, type="b", col = "purple", lwd = 1)
Image 2-Plotting a Nice Subsection-- why I want to extend X-axis
plot(data$'Pos',data$'N:S', ylim=c(0,0.5), xlim=c(163000000,165000000), col=data$Colour)
Notes:
If it matters, my graph has colored points due to color coded regions related to means and Standard Dev.
data$Colour[data$'N:S'>=data_SD1above]="orange"
Also, the only difference between data and datatest was that datatest had NA values removed.
Image 1: All Positions-Messy
Image 2: Zoomed In to see trends
Image 3: All positions with the two attempted trendlines
So it seems like that you want to resize the width of the graph for the visualization.
if you use Rstudio, there is an output option which changes the width and height of the graph.
if you use the console, you can save your plot with width and height. for example
png("mychromosome.png".width=1000,height=300)
plot(..blah..blah..)
dev.off()
I hope it will help you.

Why are all relevant tick-marks not plotted on the X-axis?

I often determine that when plotting in R not all relevant tick-marks are drawn. Relevant here means that there is data present.
See this example
> set.seed(NULL)
> d <- data.frame(a=sample(1:10, replace=TRUE), b=sample(11:30))
> plot(d)
The resulting plot where you can see values on the X-axis at 3, 5, 7 and 9. But the tick-marks for them are missing.
The focus of my question is to understand why R acts like that. What is the algorithm and logic behind it?
btw: I know how to solve it. I can draw the X-axis myself. But that is not part of the question.
You could find a brief description of the algorithm for plotting the tick marks using?axis.
plot() is a generic function to plot a wide sort of data. In your example, you are using discrete data. For continuous data, it does not make much sense to have a single tick mark for every single value, which would make unreadable the axes.
However, you can easily adjust the ticks in your plot using axis()

R: setting label spacing and position on a bar plot

I want to present percentages over a 24h period in 15 min intervals as a bar plot.
When I use barplot(), the labels for those timepoints are more or less randomly chosen by R (depending on how I format the window. I know it's not random, but it's not what I want either). I would rather have them evenly spaced at 1 h intervals (that is every 4th bar).
I have searched extensively on this and know i can add labels later with axis() but I have not found a way to set which bars are labeled and which are left blank.
So here is an example. Sorry for the long lines:
x<-sample(1:100,96)
Labels<-c("09","09:15","09:30","09:45","10:00","10:15","10:30","10:45","11","11:15","11:30","11:45","12","12:15","12:30","12:45","13","13:15","13:30","13:45","14","14:15","14:30","14:45","15","15:15","15:30","15:45","16","16:15","16:30","16:45","17","17:15","17:30","17:45","18","18:15","18:30","18:45","19","19:15","19:30","19:45","20","20:15","20:30","20:45","21","21:15","21:30","21:45","22","22:15","22:30","22:45","23","23:15","23:30","23:45","00","00:15","00:30","00:45","01","01:15","01:30","01:45","02","02:15","02:30","02:45","03","03:15","03:30","03:45","04","04:15","04:30","04:45","05","05:15","05:30","05:45","06","06:15","06:30","06:45","07","07:15","07:30","07:45","08","08:15","08:30","08:45")
names(x)<-Labels
barplot(x)
I do not think you can force R to show every label if it does not have enough space. But at least if you want to add the labels every 1h, the following code should work :
x<-sample(1:100,96)
Labels<-c("09","09:15","09:30","09:45","10","10:15","10:30","10:45","11","11:15","11:30","11:45","12","12:15","12:30","12:45","13","13:15","13:30","13:45","14","14:15","14:30","14:45","15","15:15","15:30","15:45","16","16:15","16:30","16:45","17","17:15","17:30","17:45","18","18:15","18:30","18:45","19","19:15","19:30","19:45","20","20:15","20:30","20:45","21","21:15","21:30","21:45","22","22:15","22:30","22:45","23","23:15","23:30","23:45","00","00:15","00:30","00:45","01","01:15","01:30","01:45","02","02:15","02:30","02:45","03","03:15","03:30","03:45","04","04:15","04:30","04:45","05","05:15","05:30","05:45","06","06:15","06:30","06:45","07","07:15","07:30","07:45","08","08:15","08:30","08:45")
b=barplot(x,axes = F)
axis(2)
axis(1,at=c(b[seq(1,length(Labels),4)],b[length(b)]+diff(b)[1]),labels = c(Labels[seq(1,length(Labels),4)],"09"))

Binary spark lines with R

I'm looking to plot a set of sparklines in R with just a 0 and 1 state that looks like this:
Does anyone know how I might create something like that ideally with no extra libraries?
I don't know of any simple way to do this, so I'm going to build up this plot from scratch. This would probably be a lot easier to design in illustrator or something like that, but here's one way to do it in R (if you don't want to read the whole step-by-step, I provide my solution wrapped in a reusable function at the bottom of the post).
Step 1: Sparklines
You can use the pch argument of the points function to define the plotting symbol. ASCII symbols are supported, which means you can use the "pipe" symbol for vertical lines. The ASCII code for this symbol is 124, so to use it for our plotting symbol we could do something like:
plot(df, pch=124)
Step 2: labels and numbers
We can put text on the plot by using the text command:
text(x,y,char_vect)
Step 3: Alignment
This is basically just going to take a lot of trial and error to get right, but it'll help if we use values relative to our data.
Here's the sample data I'm working with:
df = data.frame(replicate(4, rbinom(50, 1, .7)))
colnames(df) = c('steps','atewell','code','listenedtoshell')
I'm going to start out by plotting an empty box to use as our canvas. To make my life a little easier, I'm going to set the coordinates of the box relative to values meaningful to my data. The Y positions of the 4 data series will be the same across all plotting elements, so I'm going to store that for convenience.
n=ncol(df)
m=nrow(df)
plot(1:m,
seq(1,n, length.out=m),
# The following arguments suppress plotting values and axis elements
type='n',
xaxt='n',
yaxt='n',
ann=F)
With this box in place, I can start adding elements. For each element, the X values will all be the same, so we can use rep to set that vector, and seq to set the Y vector relative to Y range of our plot (1:n). I'm going to shift the positions by percentages of the X and Y ranges to align my values, and modified the size of the text using the cex parameter. Ultimately, I found that this works out:
ypos = rev(seq(1+.1*n,n*.9, length.out=n))
text(rep(1,n),
ypos,
colnames(df), # These are our labels
pos=4, # This positions the text to the right of the coordinate
cex=2) # Increase the size of the text
I reversed the sequence of Y values because I built my sequence in ascending order, and the values on the Y axis in my plot increase from bottom to top. Reversing the Y values then makes it so the series in my dataframe will print from top to bottom.
I then repeated this process for the second label, shifting the X values over but keeping the Y values the same.
text(rep(.37*m,n), # Shifted towards the middle of the plot
ypos,
colSums(df), # new label
pos=4,
cex=2)
Finally, we shift X over one last time and use points to build the sparklines with the pipe symbol as described earlier. I'm going to do something sort of weird here: I'm actually going to tell points to plot at as many positions as I have data points, but I'm going to use ifelse to determine whether or not to actually plot a pipe symbol or not. This way everything will be properly spaced. When I don't want to plot a line, I'll use a 'space' as my plotting symbol (ascii code 32). I will repeat this procedure looping through all columns in my dataframe
for(i in 1:n){
points(seq(.5*m,m, length.out=m),
rep(ypos[i],m),
pch=ifelse(df[,i], 124, 32), # This determines whether to plot or not
cex=2,
col='gray')
}
So, piecing it all together and wrapping it in a function, we have:
df = data.frame(replicate(4, rbinom(50, 1, .7)))
colnames(df) = c('steps','atewell','code','listenedtoshell')
BinarySparklines = function(df,
L_adj=1,
mid_L_adj=0.37,
mid_R_adj=0.5,
R_adj=1,
bottom_adj=0.1,
top_adj=0.9,
spark_col='gray',
cex1=2,
cex2=2,
cex3=2
){
# 'adJ' parameters are scalar multipliers in [-1,1]. For most purposes, use [0,1].
# The exception is L_adj which is any value in the domain of the plot.
# L_adj < mid_L_adj < mid_R_adj < R_adj
# and
# bottom_adj < top_adj
n=ncol(df)
m=nrow(df)
plot(1:m,
seq(1,n, length.out=m),
# The following arguments suppress plotting values and axis elements
type='n',
xaxt='n',
yaxt='n',
ann=F)
ypos = rev(seq(1+.1*n,n*top_adj, length.out=n))
text(rep(L_adj,n),
ypos,
colnames(df), # These are our labels
pos=4, # This positions the text to the right of the coordinate
cex=cex1) # Increase the size of the text
text(rep(mid_L_adj*m,n), # Shifted towards the middle of the plot
ypos,
colSums(df), # new label
pos=4,
cex=cex2)
for(i in 1:n){
points(seq(mid_R_adj*m, R_adj*m, length.out=m),
rep(ypos[i],m),
pch=ifelse(df[,i], 124, 32), # This determines whether to plot or not
cex=cex3,
col=spark_col)
}
}
BinarySparklines(df)
Which gives us the following result:
Try playing with the alignment parameters and see what happens. For instance, to shrink the side margins, you could try decreasing the L_adj parameter and increasing the R_adj parameter like so:
BinarySparklines(df, L_adj=-1, R_adj=1.02)
It took a bit of trial and error to get the alignment right for the result I provided (which is what I used to inform the default values for BinarySparklines), but I hope I've given you some intuition about how I achieved it and how moving things using percentages of the plotting range made my life easier. In any event, I hope this serves as both a proof of concept and a template for your code. I'm sorry I don't have an easier solution for you, but I think this basically gets the job done.
I did my prototyping in Rstudio so I didn't have to specify the dimensions of my plot, but for posterity I had 832 x 456 with the aspect ratio maintained.

Resources