Plots in for loop of R markdown not working - r

I am trying to use for loop in R markdown but it is not working for some reason. Here is the code:
```{r}
for (i in 1:length(endothelial_ids)) {
id <- endothelial_ids[i]
sym <- neuron_symbols[i]
VlnPlot(object = seurat_object, features.plot = id, do.return = TRUE) + labs(title = sym)
renderPlot({
fp <- FeaturePlot(object = seurat_object, features.plot = id, cols.use = c("grey", "blue"),
reduction.use = "tsne", do.return = TRUE)
lapply(fp, function(x){x + labs(title = sym)})
})
}
```
Without for loop the code is working and the generated .html report file looks good.
In the console I see several warnings:
output file: /private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl/cell_type_assignments.knit.md
Warning in file.rename(from, to) :
cannot rename file '/private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl/file613d370b37d8_files/figure-html' to '/private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl//private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl/file613d370b37d8_files/figure-html', reason 'No such file or directory'
Warning in file.rename(from, to) :
cannot rename file '/private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl//private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl/file613d370b37d8_files/figure-html' to '/private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl/file613d370b37d8_files/figure-html', reason 'No such file or directory'
Output created: /private/var/folders/hq/5ygqq7yn2hd0ln4kznxvx5j80000gn/T/Rtmpj7bedl/file613d370b37d8.html
Any suggestions would be greatly appreciated.
Update
If I wrap VlnPlot in print() function, it draws it, but not FeaturePlot:
print(VlnPlot(object = seurat_object, features.plot = id, do.return = TRUE) + labs(title = sym))
print(renderPlot({
fp <- FeaturePlot(object = seurat_object, features.plot = id, cols.use = c("grey", "blue"),
reduction.use = "tsne", do.return = TRUE)
lapply(fp, function(x){x + labs(title = sym)})
}))
And in place of the FeaturePlot I see the following in the report:
If I remove renderPlot() function and wrap lapply() in print(), it is printing me two plots instead of one: with the original wrong title and with the final correct one. So, I need a way to avoid printing the original one that happens just from the code:
fp <- FeaturePlot(object = seurat_object, features.plot = id, cols.use = c("grey", "blue"),
reduction.use = "tsne", do.return = TRUE)

Related

saving and naming files in R automatically based on input filename

I have generated several Utilisation Distributions (UD) with AdehabitatHR and stored them as Geotiffs. I am now using the same UDs with the Lattice package to generate some maps and saving them to a high-res tiff image with LZW compression. Problem is that I have literally hundreds of maps to make, save and name. Is there a way automatically do this once i have loaded all the necessary files from a directory? Each one of my UDs has the following structure of the filename "UD_resolution_species_area_year_season. tif" and in the final name I give to my map I would like to keep the same structure (or entire filename) but add the prefix "blablabla_" e.g. "blablabla_UD_resolution_species_area_year_season.tiff". The image also include a main name, a capital letter, which should also change.
At the moment I am using the following:
rlist = list.files(getwd(), pattern = "tif$", full.names = FALSE)
for (i in rlist) {
assign(unlist(strsplit(i, "[.]"))[1], raster(i))
}
shplist = list.files(getwd(), pattern = "shp$", full.names = FALSE)
for (i in shplist) {
assign(unlist(strsplit(i, "[.]"))[1], readOGR(i))
}
UD <- 'UD_resolution_species_area_year_season'
ext <- extent(UD) + 0.3 # set the extent for the plot
aa <-
quantile(UD,
probs = c(0.25, 0.75),
type = 8,
names = TRUE)
my.at <- c(aa[1], aa[2])
my.at <- round(my.at, 3)
maxval <- maxValue(UD)
tiff(
"C:/myworkingdirectory/maps/blablabla_UD_resolution_species_area_year_season.tiff",
res = 600,
compression = "lzw",
width = 15,
height = 15,
units = "cm"
)
levelplot(
UD,
xlab = "",
ylab = "",
xlim = c(ext[1], ext[2]),
ylim = c(ext[3], ext[4]),
margin = FALSE,
contour = FALSE,
col.regions = viridis(1000),
colorkey = list(at = seq(0, maxval)),
main = "A",
maxpixels = 2e5
) + latticeExtra::layer(sp.polygons(Land, fill = "grey50", col = NA)) + contourplot(
`UD`,
at = my.at[1],
labels = FALSE,
margin = FALSE,
lty = 2,
col = "orange",
pretty = TRUE
) + contourplot(
UD,
at = my.at[2],
labels = FALSE,
margin = FALSE,
lty = 2,
col = "red",
pretty = TRUE,
)
dev.off()
It is a common beginners mistake to use assign. Do not use it, it creates the type of trouble you are now facing. In stead, you can make lists and/or use a loop.
Also what you are asking is basic R stuff, but you are complicating the question with adding lots of irrelevant detail about setting the extent, and levelplot. It is better to learn about doing these basic things by removing the clutter and focus on a simple case first. That is also how you should write questions for this forum.
In essence you have a bunch of files you want to process. Below I show how you can loop over a vector of the names and then loop and do what you need to do in that loop.
library(raster)
rastfiles <- list.files(pattern = "tif$", full.names=TRUE)
outputfiles <- file.path("output/path", paste0("prefix_", basename(rastfiles)))
for (i in 1:length(rastfiles))
r <- raster(rastfiles[i])
png(outputfiles[i])
plot(r)
dev.off()
}
You can also first read all the files into a list
rastfiles <- list.files(pattern = "tif$", full.names=TRUE)
rlist <- lapply(rastfiles, raster)
names(rlist) <- gsub(".tif$", "", basename(rastfiles))
rastfiles <- list.files(pattern = "shp$", full.names=TRUE)
slist <- lapply(shpfiles, readOGR)
names(slist) <- gsub(".shp$", "", basename(shpfiles))
And perhaps create a vector of output filenames
outputtif <- file.path("output/dir", basename(rastfiles))
And then loop over the items in the list, or the output filenames

How to make inactive multiple line R code in a script

I do have a long R script and I don't want to delete a part of this R script. Is there any way to avoid running this multiple line R code in the script or should I need to insert # at the beginning of each of these lines?
I don't want to run this whole below code but want to run the code which follow it?
alpha = 0.01
sigtabresTreatment6Genus_T1_vs_T3 = resTreatment6Genus_T1_vs_T3[which(resTreatment6Genus_T1_vs_T3$padj < alpha), ]
sigtabresTreatment6Genus_T1_vs_T3 = cbind(as(sigtabresTreatment6Genus_T1_vs_T3, "data.frame"), as(tax_table(physeq6Genus)[rownames(sigtabresTreatment6Genus_T1_vs_T3), ], "matrix"))
head(sigtabresTreatment6Genus_T1_vs_T3)
dim(sigtabresTreatment6Genus_T1_vs_T3)
library("ggplot2")
theme_set(theme_bw())
scale_fill_discrete <- function(palname = "Set1", ...) {
scale_fill_brewer(palette = palname, ...)
}
# Phylum order
x = tapply(sigtabresTreatment6Genus_T1_vs_T3$log2FoldChange, sigtabresTreatment6Genus_T1_vs_T3$Phylum, function(x) max(x))
x = sort(x, TRUE)
sigtabresTreatment6Genus_T1_vs_T3$Phylum = factor(as.character(sigtabresTreatment6Genus_T1_vs_T3$Phylum), levels=names(x))
# Genus order
x = tapply(sigtabresTreatment6Genus_T1_vs_T3$log2FoldChange, sigtabresTreatment6Genus_T1_vs_T3$Genus, function(x) max(x))
x = sort(x, TRUE)
sigtabresTreatment6Genus_T1_vs_T3$Genus = factor(as.character(sigtabresTreatment6Genus_T1_vs_T3$Genus), levels=names(x))
pdf("DESeq2-Soil-batch1-DEG-T1_vs_T3_pval.01.pdf", width = 8, height = 6);
ggplot(sigtabresTreatment6Genus_T1_vs_T3, aes(x=Genus, y=log2FoldChange, color=Phylum)) + geom_point(size=6)+theme(axis.text.x = element_text(angle = -90, hjust = 0, vjust=0.5))
dev.off();
write.csv(sigtabresTreatment6Genus_T1_vs_T3,"sigResult-Treatment6Genus_T1_vs_T3")
###############
Further R code that needs to run
###########
Many thanks
Yogesh

Importing a dataframe from a function to Shiny server

I need to get the dataframe from a function in rShiny server. But that function returns a Plot and the return value cannot be changed as the plots are used in the future use.
have not pasted the whole code as its like 200 lines each for the function and also for the rshiny server.
Hist_Read_data4 <- full_join(Hist_Read_data1,Hist_Read_data_opst, by = c("timestamp"))%>%
arrange(timestamp)%>%
subset(timestamp >= as.POSIXct(start_timestamp, origin = "1970-01-01") & timestamp <= as.POSIXct(end_timestamp, origin = "1970-01-01"))%>%
mutate(value.y = na.locf(value.y, na.rm = FALSE))%>%
mutate(value.y = fct_explicit_na(value.y, na_level = "None"))%>%
mutate(value.x = na.locf(value.x, na.rm=FALSE))%>%
mutate(new_value = abs(value.x - lag(value.x)))%>%
mutate(new_value = replace_na(new_value, 0))%>%
mutate(new_value = cumsum(new_value))
plot <- ggplot() +
geom_path(data = Hist_Read_data4, mapping = aes(x = timestamp, y=value.x, color = value.y), na.rm = TRUE, linejoin = 'round' , size=1.5, group = 1)
//Hist_Read_data4 is the dataframe which i need to return//
//plot is the return value of the function//
output$HoverText <- renderText({
coordinfo <- input$PlotHover
nearpts <- nearPoints(Hist_Read_data4, coordinfo, xvar= "timestamp", yvar = "value.y", threshold = 20)
})
need Hist_Read_data4 in inside nearpoints. But it cannot be accessed as its inside a function named chooseDevice() in a separate script file named data_funcs.R
I do not want to change the return value of the chooseDevice function from plot to returning this dataframe as it will complicate the whole code and 2 months work will be wasted.

Function input used as string

saving_ggplot <- function(name = 'default', plotname = last_plot()) {
image_name = paste(name, ".png", sep="")
ggsave(image_name, plot = plotname,
scale = 1,
dpi = 300, limitsize = TRUE)
}
This is my function which saves a ggplot. However, I for the life of me cannot figure out how to take the name argument as a string.
for example if someone runes saving_ggplot(FILENAME, PLOTNAME)
it will just say no object FILENAME. In python I can just capture it and use it as str(), but using as.character or toString in R still doesn't work.
Error:
saving_ggplot(weightvsageTEST, weightvsageplot)
Error in paste(name, ".png", sep = "") :
object 'weightvsageTEST' not found
Successful call using ggsave:
ggsave('weightvsage.png', plot = last_plot(),
scale = 1,
dpi = 300, limitsize = TRUE)
You can use substitute():
saving_ggplot <- function(name, plotname) {
image_name = paste0(substitute(name), ".png") # paste0 removes need for sep arg
ggsave(image_name, plot = plotname,
scale = 1,
dpi = 300, limitsize = TRUE)
}
saving_ggplot(foo, p) # saves foo.png
Alternately, if you want to stay within tidyverse quasiquotation syntax, use enexpr() instead:
enexpr(name) # instead of substitute(name)
Data:
N <- 100
df <- data.frame(x=rnorm(n=N), y=rnorm(n=N))
p <- ggplot(df, aes(x,y)) + geom_smooth()

Problems saving several pdf files in R

I'm trying to save several xyplots created with a "for" loop in R and I'm not able to get complete pdf files (all files have the same size and I can't open them) if I execute the following loop:
for (i in 1:length(gases.names)) {
# Set ylim;
r_y <- round(range(ratio.cal[,i][ratio.cal[,i]<999], na.rm = T), digits = 1);
r_y <- c(r_y[1]-0.1, r_y[2]+0.1);
outputfile <- paste (path, "/cal_ratio_",gases.names[i], ".pdf", sep="");
dev.new();
xyplot(ratio.cal[,i] ~ data.GC.all$data.time, groups = data.vial, panel =
panel.superpose, xlab = "Date", ylab = gases.names[i], xaxt="n", ylim = r_y);
savePlot(filename = outputfile, type = 'pdf', device = dev.cur());
dev.off();
}
(a previous version was using trellis.device() instead of dev.new() + savePlot())
Do you know why I can't get good pdf files? If I do it "manually" it works... Any idea?
use pdf directly
for (i in seq_along(gases.names)) {
# Set ylim
r_y <- round(range(ratio.cal[,i][ratio.cal[,i]<999], na.rm = T), digits = 1)
r_y <- c(r_y[1]-0.1, r_y[2]+0.1)
outputfile <- paste (path, "/cal_ratio_",gases.names[i], ".pdf", sep="")
pdf(file = outputfile, width = 7, height = 7)
print(xyplot(ratio.cal[,i] ~ data.GC.all$data.time, groups = data.vial,
panel = panel.superpose, xlab = "Date", ylab = gases.names[i],
xaxt="n", ylim = r_y))
dev.off()
}

Resources