I try to create a number of PDFs with Markdown which all look the same, but use different data. For this purpose I created a little bit of code to generate random data which should be used in the creation of the PDF-File.
library(tidyverse)
r_sample <- seq(1, 5, by = 0.1)
nr_rows <- 10
df_names <- vector()
for(i in 1:2){
name <- paste0("i_",i)
i_sample <- tibble("Name" = paste0("i_", seq(1:nr_rows)))
i_sample <- i_sample %>% add_column(sample(r_sample, nr_rows, replace = TRUE)) %>%
rename("Value" = "sample(r_sample, nr_rows, replace = TRUE)")
assign(name, i_sample)
df_names[i] <- name
}
The Markdown-Script is almost empty, since it is just used for testing purposes.
---
title: "Test"
output: pdf_document
params:
data : ""
---
This is just a Test.
```{r echo = FALSE}
params$data
```. #error made intentionally!
Now I try to get the data from my R-Script into the Markdown-Script using render(). Since I want to loop over the different dataframes, I wrote a simple loop.
for(i in 1:2){
rmarkdown::render('Test.Rmd', params = list(data = df_names[i]),
output_file = glue::glue(paste0("file_", df_names[i], ".pdf")))
}
Now to the problem. Markdown understands the input of env_names[i] as a character and not as the dataframe. However if I type it manually like this:
rmarkdown::render('Test.Rmd', params = list(data = i_1), output_file = glue::glue(paste0("file_i_1.pdf")))
it works. I understand the problem, but I can't find a way to work around this.
If anyone could help I would be very glad! Thanks in advance.
The direct fix for the problem at hand is to wrap df_names[i] in get() in order to access the object whose name matches df_names[i] instead of passing the value of df_names[i] to render():
rmarkdown::render('Test.Rmd', params = list(data = get(df_names[i])),
output_file = glue::glue(paste0("file_", df_names[i], ".pdf")))
Yet, dynamically creating objects using assign in the global environment is rather unidiomatic in R – and not doing this also eradicates the need for using get() afterwards.
Therefore, I propose to write the code snippet from the question as follows:
r_sample <- seq(1, 5, by = 0.1)
nr_rows <- 10
df_list <- list()
for(i in 1:2){
df_list[[i]] <- tibble(Name = paste0("i_", seq(1:nr_rows)), Value = sample(r_sample, nr_rows, replace = TRUE))
}
Then, the loop render the documents becomes:
for(i in 1:2){
rmarkdown::render('Test.Rmd', params = list(data = df_list[[i]]),
output_file = paste0("file_i_", i, ".pdf"))
}
Related
this is probably a basic question but I still need some help to figure out what I should do.
My code is very simple, there are a bunch of calculations to get raster files stored in variables :NDWI,NDWI, VSI, etc. each calculation is based on an satellite image which has a name with the date in it. I will find a way to extract the date and store it in a variable.
In essence, what I want is a part of my code that goes over all the files created to save them as raster in a specific path of my laptop, under this format ( "variable name"_"date".tif. )
What I have for now :
Dossier <- "C:/Users/Perrin/Desktop/INRA/Raster/sentinel/L1C_T31UDR_A019210_20190225T105315/S2A_MSIL1C_20190225T105021_N0207_R051_T31UDR_20190225T125616.SAFE/GRANULE/L1C_T31UDR_A019210_20190225T105315/IMG_DATA"
library(raster)
list.files(Dossier)
Bande1 <- raster(list.files(pattern = "\\B01.jp2$"))
Bande2 <- raster(list.files(pattern = "\\B02.jp2$"))
Bande3 <- raster(list.files(pattern = "\\B03.jp2$"))
Bande4 <- raster(list.files(pattern = "\\B04.jp2$"))
NDVI <- (Bande8-Bande4)/(Bande8+Bande4)
NDWI <- (Bande8A-Bande11)/(Bande8A-Bande11)
NDDI <- (NDVI-NDWII)/(NDVI+NDWII)
writeRaster(NDWI, "C:/Users/Perrin/Desktop/INRA/résultats R/NDWI.tif", overwrite = T)
writeRaster(NDVI, "C:/Users/Perrin/Desktop/INRA/résultats R/NDVI", overwrite = T)
writeRaster(NDDI, "C:/Users/Perrin/Desktop/INRA/résultats R/NDDI.tif", overwrite = T)
Any help will be very much appreciated.
Create a list with your objects and then use Map to loop over it:
rasterList <- list(NDVI = NDVI, NDWI = NDWI, NDDI = NDDI)
filenames<-sprintf("C:/Users/Perrin/Desktop/INRA/résultats R/%s_%s.tif",
names(rasterList), format(Sys.Date(), "%Y%m%d"))
Map(writeRaster, rasterList, filenames, MoreArgs = list(overwrite = TRUE))
I was wondering whether there is a way to save a purtest - output as a LaTeX
file?
As you can see in the example-code, I have already tried to produce it via stargazer. However, the stargazer function does not support the purtest-class.
library(plm)
library(stargazer)
dat <- data.frame(entity = c(rep("a",10),rep("b",10)),year =
rep(1970:1979,2),value = rnorm(20))
pdat <- pdata.frame(dat,index = c("entity","year"))
res <- purtest(object = pdat$value,test = "ips",exo = "intercept",pmax = 1)
stargazer(summary(res),type = "latex")
I know that it is possible to extract values manually, to store them in a data.frame and eventually to save the data.frame via print.xtable as a LaTeX file.
But perhaps there is any neat solution to the problem.
Stargazer library has a lot of checks constraining the classes that can be used.
Class "purtest" is not included, but as Stargazer support exporting of "matrix" class, one can trick the restrictions. For example:
# the problem
library(plm)
library(stargazer)
dat <- data.frame(entity = c(rep("a",10),rep("b",10)),year =
rep(1970:1979,2),value = rnorm(20))
pdat <- pdata.frame(dat,index = c("entity","year"))
res <- purtest(object = pdat$value,test = "ips",exo = "intercept",pmax = 1)
# One solution: extract the parametars and place them in the matrix:
a = unlist(res$idres[[1]])
b = unlist(res$idres[[2]])
all = rbind(a, b)
class(all) <- c("matrix")
stargazer(all,type = "latex",align = T)
# need to align , else you get strange double dollar signs
Amateur user of R and just having difficulties with simplifying some code. I have a list of dataframes of test results and I would like run the sjt.corr function across these dataframes for quality assurance.
Edit
A small reproducible example:
library(sjplot)
list <- list()
list$a <- as.data.frame(cbind(c(1,2,3,4,5,6,7,8),c(1,2,3,4,5,7,6,8)))
list$b <- as.data.frame(cbind(c(1,2,3,4,5,7,6,8),c(7,6,8,5,4,3,2,1)))
list$c <- as.data.frame(cbind(c(7,6,8,5,4,3,2,1),c(1,2,3,4,5,6,7,8)))
I am not sure where my loop fails me. If you can see the error please let me know:
for (i in seq_along(list)) {
sjt.corr(
list[[i]],
na.deletion = "pairwise",
corr.method = "spearman",
file = paste("consensus", i, "html", sep = ".")
)
}
Appears to work silently, but does not save anything.
This works:
sjt.corr(
list[[1]],
na.deletion = "pairwise",
corr.method = "spearman",
file = paste("consensus", 1, "html", sep = ".")
)
So a solution from my friend is to just use lapply.
i <- 0
lapply(list, function(x) {
i <<- i + 1
sjt.corr(
x,
na.deletion = "pairwise",
corr.method = "spearman",
file = paste("consensus", i, "html", sep = "."))
})
Which works great! Still unsure why the original for loop does not work. Any reference to another similar scenario would be great.
I have a bunt of single files which need to apply a test. I need to find the way to write automatically results of each file into a file. Here is what I do:
library(ape)
stud_files <- list.files("path/dir/data",full.names = T)
for (f in stud_files) {
df <- read.table(f, header=TRUE, sep=";")
df_xts <- as.xts(df$cola, order.by = as.Date(df$colb,"%m/%d/%Y"))
pet <- testa(df_xts)
res <- data.frame(estimate = pet$estimate,
p.value=pet$p.value,
logi = pet$alternative)
write.dna(res,file = "res_testa.xls",format = "sequential")
}
This loop works well, except the last command which aim to write the results of each file consecutively, it saved only the last performance. And the results save as string, not a table as I define above (data.frame). Any idea in this case? Thanks in advance
Check help(write.dna).
write.dna(x, file, format = "interleaved", append = FALSE,
nbcol = 6, colsep = " ", colw = 10, indent = NULL,
blocksep = 1)
append a logical, if TRUE the data are appended to the file without
erasing the data possibly existing in the file, otherwise the file (if
it exists) is overwritten (FALSE the default).
Set append = TRUE and you should be all set.
As some of the comments point out, however, you are probably better off generating your table, and then writing it all at once to a file. Unless you have billions of files, you likely won't run out of memory.
Here is how I would approach this.
library(ape)
library(data.table)
stud_files <- list.files("path/dir/data",full.names = T)
sumfunc <- function(f) {
df <- read.table(f, header=TRUE, sep=";")
df_xts <- as.xts(df$cola, order.by = as.Date(df$colb,"%m/%d/%Y"))
pet <- testa(df_xts)
res <- data.table(estimate = pet$estimate,
p.value=pet$p.value,
logi = pet$alternative)
return(res)
}
lres <- lapply(stud_files, sumfunc)
dat <- rbindlist(lres)
write.table(dat,
file = "res_testa.csv",
sep = ",",
quote = FALSE,
row.names = FALSE)
I have this little problem in R : I loaded a dataset, modified it and stored it in the variable "mean". Then I used an other variable "dataset" also containing this dataset
data<-read.table()
[...modification on data...]
mean<-data
dataset<-mean
I used the variable "dataset" in some other functions of my script, etc. and at the end I want to store in a file with the name "table_mean.csv"
Of course the command write.csv(tabCorr,file=paste("table_",dataset,".csv",sep=""))
nor the one with ...,quote(dataset)... do what I want...
Does anyone know how I can retrieve "mean" (as string) from "dataset" ?
(The aim would be that I could use this script for other purposes simply changing e.g. dataset<-variance)
Thank you in advance !
I think you are trying to do something like the following code does:
data1 <- 1:4
data2 <- 4:8
## Configuration ###
useThisDataSet <- "data2" # Change to "data1" to use other dataset.
currentDataSet <- get(x = useThisDataSet)
## Your data analysis.
result <- fivenum(currentDataSet)
## Save results.
write.csv(x = result, file = paste0("table_", useThisDataSet, ".csv"))
However, a better alternative would be to wrap your code into a function and pass in your data:
doAnalysis <- function(data, name) {
result <- fivenum(data)
write.csv(x = result, file = paste0("table_", name, ".csv"))
}
doAnalysis(data1, "data1")
If you always want to use the name of the object passed into the function as part of the filename, we can use non-standard evaluation to save some typing:
doAnalysisShort <- function(data) {
result <- fivenum(data)
write.csv(x = result, file = paste0("table_", substitute(data), ".csv"))
}
doAnalysisShort(data1)