Using User-Defined "For Loop" Function to Construct a Data Frame

Using user-defined for loop function to construct a data frame

There are two problems with the function:

  1. You're overwriting Col_T with all NAs as the first statement inside the for loop.
  2. You're returning from the function inside the for loop.

Rewrite it as follows:

myfunc <- function(X, system, Title ) {
Col_T <- data.frame(matrix(NA, ncol=length(X), nrow=4 ));
for (i in 1:4)
Col_T[i,] <- colSums(X[which(df$yr==i & df$cs==system),]);
return(Col_T);
};

User defined function input to loop every row of data frame

This is a corrected version of your program:

df <- data.frame(type=c("C", "C"), marketV=c(1.1166, 1.911), S=c(20, 60), K=c(20, 56), T=c(0.333, 0.5))

IV <- function(df) {
# check if df has more then 1 row:
if (nrow(df)>1) { message("!! nrow(df)>1 !!"); return(NA) }

# Initializing of variables
r <- 0
sigma <- 0.3
sigma_down <- 0.001
sigma_up <- 1
count <- 0

type <- df$type; marketV <- df$marketV; S <- df$S; K <- df$K; T <- df$T

d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
d2 <- (log(S/K) - (sigma^2/2)*T)/(sigma*sqrt(T))

if(type=="C") {
V <- exp(-r*T)*(S*pnorm(d1) - K*pnorm(d2))
} else {
V <- exp(-r*T)*(K*pnorm(-d2) - S*pnorm(-d1)) }

difference <- V - marketV

# Root finding of sigma by Bisection method
while(abs(difference)>0.001 && count<1000) {
if(difference < 0) {
sigma_down <- sigma
sigma <- (sigma_up + sigma)/2
} else {
sigma_up <- sigma
sigma <- (sigma_down + sigma)/2
}

d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
d2 <- d1 - sigma*sqrt(T)

if(type=="C") {
V <- exp(-r*T)*(S*pnorm(d1) - K*pnorm(d2))
} else {
V <- exp(-r*T)*(K*pnorm(-d2) - S*pnorm(-d1)) }

difference <- V - marketV
count <- count + 1
}
if(count == 1000){
return(NA) # If sigma to satisfy Black76 price cannot be found
} else{
return(sigma)
}
}

sapply(split(df, seq(nrow(df))), IV)

The main thing is to run row by row through the dataframe. This is done by

sapply(split(df, seq(nrow(df))), IV)

In your original function are many errors: the biggest is accessing to S, K and so on. You might thinking taking the values from the dataframe df. But in fact you were taking the values from the workspace! I corrected this by redefining:

type <- df$type; marketV <- df$marketV; S <- df$S; K <- df$K; T <- df$T

I inserted a test for the number of rows in df, so you will get:

> IV(df)
!! nrow(df)>1 !!
[1] NA

Here is a cleaned up version of your program:

df <- data.frame(type=c("C", "C"), marketV=c(1.1166, 1.911), S=c(20, 60), K=c(20, 56), T=c(0.333, 0.5))

IV2 <- function(type, marketV, S, K, T) {
r <- 0; sigma <- 0.3
sigma_down <- 0.001; sigma_up <- 1
count <- 0

if(type=="C") {
f.sig <- function(sigma) {
d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
d2 <- d1 - sigma*sqrt(T)
exp(-r*T)*(S*pnorm(d1) - K*pnorm(d2)) - marketV
}
} else {
f.sig <- function(sigma) {
d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
d2 <- d1 - sigma*sqrt(T)
exp(-r*T)*(K*pnorm(-d2) - S*pnorm(-d1)) - marketV
}
}
ifelse(f.sig(sigma_down)*f.sig(sigma_up) < 0, uniroot(f.sig, c(sigma_down,sigma_up))$root, NA) # sigma
}

sapply(split(df, seq(nrow(df))), do.call, what="IV2")

How to use for loop to create new data frames using i in the name of data frame in R

You can try :

library(dplyr)
yearlist <- c(2013, 2014)

lapply(yearlist, function(x) {
maxyear <- x
minyear <- maxyear - 7

mutatedata %>%
filter(year>=minyear & year<=maxyear) %>%
group_by(symbol) %>%
summarize(
avgroepercent = mean(roe,na.rm = TRUE),
avgrocpercent = mean(roc, na.rm = TRUE),
epsroc = (((last(eps))/(first(eps)))^(1/(maxyear-minyear))-1)
)
}) -> data

where data is a list of dataframes. If you want to create separate dataframes you can use list2env.

names(data) <- paste0('metrics_', yearlist)
list2env(data, .GlobalEnv)

Applying For loop with def function to generate other DataFrame?

Yes you could just do:

for item in medal['event_gender'].unique():
globals()[item] = gender(medal, item)

But why do this? Maintain your dataframe as it is and work on it with groupings. It is easier that way to do same computations on different groups of the same dataframe rather than doing same computation on different dataframes

User defined function within for-loops

If I understood your question properly, then you need to assign the results in your last 'for' loop:

for(i in 1:num_students){
if(i == 1) out <- NULL
out <- c(out, emotion_difference_fun(probs))
}
out

Is that what you are looking for?

What I am unclear about though, is why in your second code section you are not looking for a 5*5 matrix. Eventually, when running that code, it doesn't matter that you did it for i = 5 students, because it will only save in row_prob your last iteration (student = 5).

Using a for loop to apply a function to a list in R

The df doesn't update the original object 'df1', 'df2' in the global env. If we want, use assign (or better is to keep it in a list)

# // create a named `list`
dataframes = list(df1,df2,df3,df4)
names(dataframes) <- c("df1", "df2", "df3", "df4")
# // loop over the names of the list
for(nm in names(dataframes)) {
# // get the value of the object from the names
df <- get(nm)
# // create the new columns
df[paste0("lag", 1:12)] <- lapply(1:12, lag, x=df[,2])
df[paste0("lead", 1:12)] <- lapply(1:12, lead, x=df[,2])
# // assign to update the original object
assign(nm, df)
}

It may be better to keep it in a list

dataframes2 <- lapply(dataframes, function(df) {
df[paste0("lag", 1:12)] <- lapply(1:12, lag, x=df[,2])
df[paste0("lead", 1:12)] <- lapply(1:12, lead, x=df[,2])
df
})

The list output can be used to update the original objects with list2env though not recommended

list2env(dataframe2, .GlobalEnv)

How to loop/map a function over a data frame with the output named according to the input variables?

You can pass column names as string.

library(dplyr)
library(purrr)
library(rlang)

tbl_loadings <- function(data, depen_indepen_vars, pcs ) {
dep <- sym(depen_indepen_vars)
pcs <- sym(pcs)
loadX <- data %>%
filter(!!pcs != "NA") %>%
mutate(load = paste0(!!dep, " (", !!pcs, "), ", collapse = "")) %>%
pull(load) %>% unique()
return(loadX)
}

map(paste0('X', 1:3), tbl_loadings, data = loadings, depen_indepen_vars = "Met")

#[[1]]
#[1] "Met1 (0.5), Met2 (0.1), "

#[[2]]
#[1] "Met1 (0.1), Met3 (0.8), "

#[[3]]
#[1] "Met1 (0.3), Met2 (0.9), "

R: build data frame in user defined function

rbinding data.frames is very slow in my experience, but anyway: replace your placeholder with return(data.frame(x,calc)).

After changing the function, probably the easiest way to get them all into one data.fameis through:

output<-do.call(rbind, lapply(letters, functest))

applying a user defined function to a dataframe

A simple fix would be:

for group in Final.groupby('Key'): 
# group is a tuple where the first value is the Key and the second is the dataframe
result = regression(group[1])
# do xyz with result

EDIT:

you do not have to convert group into a data frame again and can use it directly as it is already in the proper format.

# this line is not necessary
Final1 = pd.DataFrame(Final1)

judging from the error it is clear that the group that you have passed into the train_test_split function does not have enough records. which is quite evident in the error message. you will have to handle for such errors using try, except.



Related Topics



Leave a reply



Submit