How to give a formula values in a loop - r

I have a program that is supposed to create a pdf file of actograms given a csv of activity and time. I need to loop through multiple activity columns, one for each subject. The first activity column is column 3. Here is the relevant code:
pdf("All Actograms.pdf")
for(i in 3:(length(dat) - 1)) {
activity <- colnames(dat)[i]
# Plot the actogram
print(actogram(activity~datetime, dat=dat, col="black", main=colnames(dat)[i], strip.left.format="%m/%d", doublePlot = TRUE, scale=0.75))
}
dev.off()
When I call my actogram function, I get the error "non-numeric argument to binary operator." The problem is the formula "activity~datetime," because datetime is a column name and activity should be too. If I try it out of the loop, with the name of an activity column rather than a variable containing the name, it works fine. Upon debugging, I found the actogram function is receiving the string "activity," rather than the variable activity. I don't really understand formulas, but I want to know if there's any way to accomplish what I'm trying to do, which is loop through many columns, changing the column before the "~" each time I call the actogram function. I'm very new to R.
Thanks!

We do not have the data you are working on but I think the simplest thing you can do is the following:
pdf("All Actograms.pdf")
for(i in 3:(length(dat) - 1)) {
activity <- colnames(dat)[i]#save the name of the column I
colnames(dat)[i] <- "activity" # change the name of column I to activity
# Plot the actogram
print(actogram(activity~datetime, dat=dat, col="black", main=activity, strip.left.format="%m/%d", doublePlot = TRUE, scale=0.75))
colnames(dat)[i] <- activity # change back the name of the column I to its original name
}
dev.off()
Hopefully it works.

Related

User defined function with ticker as input?

Here is my code right now:
f=function(Symbol, start, end, interval){
getSymbols(Symbols=Symbol, from=start, to= end)
Symbol=data.frame(Symbol)
a=length(Symbol$Symbol.Adjusted)
b=a/interval
c=ceiling(b)
origData=as.data.frame(matrix(`length<-`(Symbol$Symbol.Adjusted, c * interval), ncol = interval, byrow = TRUE))
return(origData)
}
f("SPY", "2012-01-01", "2013-12-31", 10)
Next I need to Get the adjusted close price and consider this price data only for following tasks. Split daily stock adjusted close price into N blocks as rows in a data frame. So that each block containing M days (columns) data, where M equals to the time interval value. It’s referred as origData in my code.
The function is supposed to return the data frame origData, but whenever I try running this it tells me that the Symbol data frame is empty. How do I need to change my function to get the data frame output?
#IRTFM's observations are correct. Incorporating those changes you can change your function to :
library(quantmod)
f = function(Symbol, start, end, interval){
getSymbols(Symbols=Symbol, from=start, to= end)
data= get(Symbol)
col = data[, paste0(Symbol, '.Adjusted')]
a=length(col)
b=a/interval
c=ceiling(b)
origData= as.data.frame(matrix(`length<-`(col, c * interval),
ncol = interval, byrow = TRUE))
return(origData)
}
f("SPY", "2012-01-01", "2013-12-31", 10)
I haven't figured out what the set of expressions inside the data.matrix call is supposed to do and you made no effort to explain your intent. However, your error occurs farther up the line. If you put in a debugging call to str(Symbol) you will see that Symbol will evaluate to "SPY" but that is just a character value and not an R object name. The object you wnat is named SPY and the way to retrieve an object's value when you can only have access to a character value is to use the R function get, So try adding this after the getSymbols call inside the function:
library(quantmod) # I'm assuming this was the package in use
...
Symbol=data.frame( get(Symbol) )
str(Symbol) # will print the result at your console
....
# then perhaps you can work on what you were trying inside the data.matrix call
You will also find that the name Symbol.Adjusted will not work (since R is not a macro language). You will need to do something like:
a=length( Symbol[[ paste0(Symbol, ".Adjusted")]] )
Oh wait. You overwrote the value for Symbol. That won't work. You need to use a different name for your dataframe. So why don't you edit your question to fix the errors I've identified so far and also describe what you are trying to do when you were using as.data.frame.

Fill an object with the results of every loop iteration in R

first time asker here. I have recently strated working with R and I hope I could get some help with an issue. The problem is probably easy to solve but I haven't been able to find an answer by myself and my research hasn't been succesful either.
Basically I need to create a single object based on the input of a loop. I have 7 simulated asset returns, these objects contain the results from a simulation I ran. I want to match the columns from every object and form a combined one (i.e. every column 1 forms an object), which will be used for some calculations.
Finally, the result from each iteration should be stored on a single object that has to be available outside the loop for further analysis.
I have created the following loop, the problem is that only the result from the last iteration is being written in the final object.
# Initial xts object definition
iteration_returns_combined <- iteration_returns_draft_1
for (i in 2:10){
# Compose object by extracting the i element of every simulation serie
matrix_daily_return_iteration <- cbind(xts_simulated_return_asset_1[,i],
xts_simulated_return_asset_2[,i],
xts_simulated_return_asset_3[,i],
xts_simulated_return_asset_4[,i],
xts_simulated_return_asset_5[,i],
xts_simulated_return_asset_6[,i],
xts_simulated_return_asset_7[,i])
# Transform the matrix to an xts object
daily_return_iteration_xts <- as.xts(matrix_daily_return_iteration,
order.by = index(optimization_returns))
# Calculate the daily portfolio returns using the iteration return object
iteration_returns <- Return.portfolio(daily_return_iteration_xts,
extractWeights(portfolio_optimization))
# Create a combined object for each iteration of portfolio return
# This is the object that is needed in the end
iteration_returns_combined <<- cbind(iteration_returns_draft_combined,
iteration_returns_draft)
}
iteration_returns_combined_after_loop_view
Could somebody please help me to fix this issue, I would be extremely grateful for any information anyone can provide.
Thanks,
R-Rookie
By looking at the code, I surmise that the error is in the last line of your for loop.
iteration_returns_draft_combined
was never defined, so it is assumed to be NULL. Essentially, you only bind columns of the results from each iteration to a NULL object. Hence the output of your last loop is also bound by column to a NULL object, which is what you observe. Try the following:
iteration_returns_combined <- cbind(iteration_returns_combined,
iteration_returns)
This should work, hopefully!
Consider sapply and avoid expanding an object within a loop:
iteration_returns_combined <- sapply(2:10, function(i) {
# Compose object by extracting the i element of every simulation serie
matrix_daily_return_iteration <- cbind(xts_simulated_return_asset_1[,i],
xts_simulated_return_asset_2[,i],
xts_simulated_return_asset_3[,i],
xts_simulated_return_asset_4[,i],
xts_simulated_return_asset_5[,i],
xts_simulated_return_asset_6[,i],
xts_simulated_return_asset_7[,i])
# Transform the matrix to an xts object
daily_return_iteration_xts <- as.xts(matrix_daily_return_iteration,
order.by = index(optimization_returns))
# Calculate the daily portfolio returns using the iteration return object
iteration_returns <- Return.portfolio(daily_return_iteration_xts,
extractWeights(portfolio_optimization))
})
And if needed to column bind first vector/matrix, do so afterwards:
# CBIND INITIAL RUN
iteration_returns_combined <- cbind(iteration_returns_draft_1, iteration_returns_combined)

Dynamically assign variable names for vectors in R?

I'm new to R and I am trying to create variables referencing vectors within a for loop, where the index of the loop will be appended to the variable name. However, the following code below, where I'm trying to insert the new vectors into the appropriate place in the larger data frame, is not working and I've tried many variations of get(), as.vector(), eval() etc. in the data frame construction function.
I want num_incorrect.8 and num_incorrect.9 to be vectors with a value of 0 and then be inserted into mytable.
cols_to_update <- c(8,9)
for (i in cols_to_update)
{
#column name of insertion point
insertion_point <- paste("num_correct",".",i,sep="")
#create the num_incorrect col -- as a vector of 0s
assign(paste("num_incorrect",".",i,sep=""), c(0))
#index of insertion point
thespot <- which(names(mytable)==insertion_point)
#insert the num_incorrect vector and rebuild mytable
mytable <- data.frame(mytable[1:thespot], as.vector(paste("num_incorrect",".",i,sep="")), mytable[(thespot+1):ncol(mytable)])
#update values
mytable[paste("num_incorrect",".",i,sep="")] <- mytable[paste("num_tries",".",i,sep="")] - mytable[paste("num_correct",".",i,sep="")]
}
When I look at how the column insertion went, it looks like this:
[626] "num_correct.8"
[627] "as.vector.paste..num_incorrect........i..sep........2"
...
[734] "num_correct.9"
[735] "as.vector.paste..num_incorrect........i..sep........3"
Basically, it looks like it's taking my commands as literal text. The last line of code works as expected and creates new columns at the end of the data frame (since the line before it didn't insert the column into the proper place):
[1224] "num_incorrect.8"
[1225] "num_incorrect.9"
I am kind of out of ideas, so if someone could please give me an explanation of what's wrong and why, and how to fix it, I would appreciate it. Thanks!
The mistake is in the second last lines of your code, excluding the comments where you are creating the vector and adding it to your data frame.
You just need to add the vector and update the name. You can remove the assign function as it's not creating a vector instead just assigning a value of 0 to the variable.
Instead of the second last line of your code put the code below and it should work.
#insert the vector at the desired location
mytable <- data.frame(mytable[1:thespot], newCol = vector(mode='numeric',length = nrow(mytable)), mytable[(thespot+1):ncol(mytable)])
#update the name of new location
names(mytable)[thespot + 1] = paste("num_incorrect",".",i,sep="")

R looping through categorical variables

I have the variables "data$LINE" and "data$STATE" and I want to use a loop to rename them with out the "data$". Then I want the same loop to input "LINE" and "STATE" into my code, but I also want "data$LINE" and "data$STATE" to run in the loop as well. The reason is that I have two graphing functions, one depending one the name i.e. "LINE", the other depending on "data$LINE" and I want these two graphs to run for "LINE" and "STATE" so after the loop, 4 graphs are made.
The code is:
for(variable in c(data$LINE, data$STATE)) {
variable_name <- sub("data$", replacement = "", "data$variable", fixed = TRUE)
whatevergraphingfunction(variable)
differentgraphingfunction(variable_name)
}
This is not working right (it doesn't seem to create the 2 variable_names), any help would be appreciated.
I think your issue is in for(variable in c(data$LINE, data$STATE)) , because you are trying to concatenate 'symbols' start with strings for the for function, and them convert them to names after sub() has run.
#start with variables as strings
for(variable in c("data$LINE", "data$STATE")) {
#Remove the 'data$'
variable_name <- sub("data$", replacement = "", variable, fixed = TRUE)
# convert strings back to names
as.name(variable)
as.name(variable_name)
# Graph
whatevergraphingfunction(variable)
differentgraphingfunction(variable_name)
}
Without knowing how LINE and STATE will be used, I am not sure if you need to call them as names. If not, just delete the as.name(variable_name) line.
Let me know if this worked for you.

R : rename columns time series data

I am trying to rename the columns of a time series using assign function as follows -
assign(colnames(paste0(<logic_to_get_dataset>)),
c(<logic_to_get_column_names>))
I am getting a warning : In assign(colnames(get(paste0("xvars_", TopVars[j, 1], "_lag", :
only the first element is used as variable name
also, the column name assignment does not happen. I think this is happening because of colnames() function. Is there a workaround ?
The issue is that assign only looks at the first element of the vector.
You can try this, for example:
df = data.frame(x = 1:3, y = 4:2)
within(df, assign(colnames(df),c('a','b'))
You'll notice that R only looks at the first variable, and it tries to reassign the values that are described by those column names to the second value. This behavior is obviously not what you're looking for.
Unfortunately, it's kind of hackey, but you can always use something like this
data.frame.name = get_df()#some function that returns text
data.frame.columns = get_cols()#some function that returns text
eval(parse(text = paste0('colnames(',data.frame.name,') = c(',
paste(data.frame.columns,collapse = ','),')')))
I prefer to avoid doing these kinds of expressions, but it should work as intended.
Here it goes -
temp_var <- paste0('colnames(var_',TopLines[j,1],'_lag',get(paste0('uniqLg_',TopLines[j,1]))[k,],'_',get(paste0('uniqLg_',TopLines[j,1]))[k,]+12 ,
') <- c(gsub( "xt',get(paste0('uniqLg_',TopLines[j,1]))[k,],'" , "xt',get(paste0('uniqLg_',TopLines[j,1]))[k,],'__',get(paste0('uniqLg_',TopLines[j,1]))[k,]+12,
'", colnames(var_',TopLines[j,1],'_xt',get(paste0('uniqLg_',TopLines[j,1]))[k,],')))')
print(temp_var )
eval(parse( text=temp_var ))
where TopLines is a data frame with one column and contains a list of lines. The only problem with this method is, I can't test the output of eval unless I actually open the dataset and see if the changes have been affected.

Resources