Using a function using loop elements - r

I want to loop through a list of elements and use them in a function. Here is a partial code, from a t-test in jamovi package.
j = c("K1", "K2")
for (i in j) {
temp1 <- jmv::ttestIS(
formula = i ~ T1,
data = data1,
vars = i,
students = FALSE,
eqv = TRUE)
temp1
}
I get the error that the argument i is not in the dataset. I suppose it's because the function sees i as itself and not K1. Any ideas how to access the loop elements in the function?
ps. I can provide a reproducible code if needed.

You can use as.formula(). However, please note that you are overwriting temp1 for each iteration of j here; was that your intention?
for (i in j) {
formula = as.formula(paste(i,"~T1"))
temp1 <- jmv::ttestIS(
formula = formula,
data = data1,
students = FALSE,
eqv = TRUE)
temp1
}

Instead of using
for (i in j)
use
for (in in 1:length(j))

Related

Dynamically create subsets in R with a for loop

I am trying to create different subsets out of a table and with each iteration I want to shift one column upwards. So far I realized this with this code but undynamically:
subset_cor_lag00 <- subset(data_24h, select = c(price_return, sentiment_return, tweet_return))
korr_tab_lag00 <- cor(subset_cor_lag00)
subset_cor_lag01 <- transform(subset_cor_lag00, price_return = lead(price_return))
subset_cor_lag01 <- na.omit(subset_cor_lag01)
korr_tab_lag01 <- cor(subset_cor_lag01)
But now I tried to do this dynamically but I got stuck with it. So maybe someone has a hint. I really would appreciate it. I tried this
for(i in 1:5) {
paste0("subset_cor_lag0", i) <- transform(paste0("subset_cor_lag0", i-1), price_return = lead(price_return))
paste0("subset_cor_lag0", i) <- na.omit(paste0("subset_cor_lag0", i))
paste0("korr_tab_lag0", i) <- cor(paste0("subset_cor_lag0", i))
}
You can use assign for this, but usually having sequentially named variables isn't nice to work with. The better way is to use a list:
subset_cor_lag = list(subset(data_24h, select = c(price_return, sentiment_return, tweet_return)))
for(i in 2:6) {
temp = transform(subset_cor_lag[[i - 1]], price_return = lead(price_return))
subset_cor_lag[[i]] = na.omit(temp)
}
korr_tab = lapply(subset_cor_lag, cor)
## add names, if desired:
name_vec = paste0("lag", 0:5)
names(subset_cor_lag) = name_vec
names(korr_tab) = name_vec
You can then access, e.g., subset_cor_lag[["lag2"]] or subset_cor_lag[[3]], which is easy to do programmatically in a loop or with lapply.
See my answer at How to make a list of data frames? for more discussion and examples.

How to use apply function with list of functions with multiple argument in r?

I repeat more than 10 functions, three or more times for each function in R!! it is very confusing and wasting my time. I understand the idea of apply function but very basic and need a help with this issue.
I have these functions (part of my whole functions):
sel_1 <- lower.tri(fam1) # selector for lower triangular matrix
if (check.pars & (any(fam1 != 0) | any(!is.na(par11)))) {
BiCopCheck(fam1[sel_1], par11[sel_1], par21[sel_1], call = match.call())
}
sel_2 <- lower.tri(fam2)
if (check.pars & (any(fam2 != 0) | any(!is.na(par11)))) {
BiCopCheck(fam2[sel_2], par12[sel_2], par22[sel_2], call = match.call())
}
sel_3 <- lower.tri(fam3)
if (check.pars & (any(fam3 != 0) | any(!is.na(par13)))) {
BiCopCheck(fam3[sel_3], par13[sel_3], par23[sel_3], call = match.call())
}
MixRVM1 <- list(Matrix = Matrix,
fam1 = fam1,
par11 = par11,
par21 = par21,
names = names,
MaxMat = MaxMat,
CondDistr = CondDistr)
MixRVM12 <- list(Matrix = Matrix,
fam2 = fam2,
par12 = par12,
par22 = par22,
names = names,
MaxMat = MaxMat,
CondDistr = CondDistr)
Is there an easy way to repeat these functions?
It's hard without the data, but by following these principles you should be able to improve your code:
if you don't already have your fam and par variables in a neat format (which you should if you have control over it):
fam_variables <- grep("fam[0-9]",ls(),value=TRUE)
fam_variables <- sel_variables[order(sapply(fam_variables,function(x){as.numeric(substr(x,4,nchar(x)))}))]
fam <- lapply(fam_variables,get) # assuming there's no missing sel variable from 1 to n!
par_list <- list(list(par11,par12,par13),list(par21,par22,par23))
Then you can use apply functions over these lists:
sel <- lapply(fam,lower.tri)
sapply(1:3,function(i){BiCopCheck(fam[[i]][sel[[i]]], par_list[[1]][[i]][sel[[i]]], par_list[[2]][[i]][sel[[i]]], call = match.call())})
MixRVM <- list() # we create a list, and we'll keep the same structure for every item (so the name will be the same among elements)
for (i in 1:2){
MixRVM[[i]] <- list(Matrix = Matrix,
fam = fam[[i]],
par1i = par_list[[1]][[i]],
par2i = par_list[[2]][[i]],
names = names,
MaxMat = MaxMat,
CondDistr = CondDistr)
}

Improvement upon a for-loop: create a series of subsets without looping

My objective is to create a number of time-series subsets from a list of variables. I wrote this with a for-loop. However, I'm looking for more elegant ideas on how to do with an existir R function, that doesn't require a loop.
All ideas and intros to new functions in R are much appreciated.
A reproducible example of the code:
russell_sim <- arima.sim(model=list(ar=c(.9,-.2)),n=449)
russell_sim <- ts(russell_sim, start = c(1980,1), end = c(2017,5) ,frequency = 12)
pmi_sim <- arima.sim(model=list(ar=c(.9,-.2)),n=449)
pmi_sim <- ts(russell_sim, start = c(1980,1), end = c(2017,5) ,frequency = 12)
big_list<- list(russell = russell_sim, pmi= pmi_sim)
for (i in 1: length(big_list)) {
assign(paste(names(x = big_list)[i], "_before08", sep = ""), window(big_list[[i]], start=c(1981,1), end=c(2007, 12)) )
}
Thank you.
You can make use of the handy list2env function but you will need to edit the list first to get your desired output:
# New List to edit
big_list_before08 <- big_list
# change your observations
big_list_before08 <- lapply(big_list_before08, function(x) window(x, start = c(1981,1),
end = c(2007,12)))
# change the individual list element names
names(big_list_before08) <- paste0(names(big_list),"_before08")
# save to the global environment
list2env(big_list_before08, envir = .GlobalEnv)
Let me know if you have any questions!

Paste multiple elements in R

I make this code using a for-statement. (The main purpose of this code is to list different webpages, which are obtained via httr and rvest)
r = "asdgkjkhdf"
t = "osrt"
all = c()
for(i in 1:400)
{
y = paste(r, i, sep = '')
d = paste(y, t, sep = '')
all = c(all, d)
}
all
I got things like these (pasted numbers are actually getting accumulated in the each results)
[1]asdgkjkhdf1osrt
[2]asdgkjkhdf12osrt
[3]asdgkjkhdf123osrt
[4]asdgkjkhdf1234osrt
...
But I want results like these regardless of how many numbers i put in 'for()'function.
[1]asdgkjkhdf1osrt
[2]asdgkjkhdf2osrt
...
[400]asdgkjkhdf400osrt
like these above
What should I change in order to have what I want to result in?
Should I use paste(substr(), substr(), sep='')?
If you really want to use a for-statement you can use the following
r = "asdgkjkhdf"
t = "osrt"
all = c()
for (idx in 1:400)
all = c(all, paste0(r, idx, t))
However, in R you should prefer code without for-statements since, in general, this is less readable and hurts performance. The solution without the for-statement (given by Roland in the comments) equals
all <- paste0(r, 1:400, t)
Note that paste0("string")is just a short notation for paste("string", sep='').

Saving more then 1 models in a list in R

I have a matrix of ts values and i need to save all garch models (models construct for each column af a matrix) in a list. I tried this code and it doesn't work (i can't understand why):
model = list()
for (i in ncol(p)) {
if (length(model) == 0) {
model = list(ugarchfit(data=p[-1,i], spec=spec))
} else {
bufer = ugarchfit(data=p[-1,i], spec=spec)
model = cbind(model, bufer)
}
}
Can somebody help me to cope with this? I need to address this list with the column index and get a model for this column index.
Thanks!
It is better the create the list with final dimensions rather that to create a growing list.
models <- vector("list", ncol(p))
Then overwrite the relevant element of the list
for (i in seq_len(ncol(p))) {
models[[i]] <- ugarchfit(data = p[-1, i], spec = spec)
}
Another solution would to use lapply
models <- lapply(
seq_len(ncol(p)),
function(i) {
ugarchfit(data = p[-1, i], spec = spec)
}
)
Note that your code will be more clear is you use = for passing arguments to a function and <- for assignments.

Resources