How can I make a loop that calls dataframes - r

I have the wrote the code below for a transformation of rows of a dataframe to colums
RowsToColums <- function(df)
{
model = list()
for(i in seq_along(df))
{
if(i>4)
{
dataf <- data.frame(names = df[1], Year=colnames(df[i]), index = df[,i:i])
names(dataf)[3]<- toString(df[[3]][2])
names(dataf)[1]<- "Country"
model[[i]] <- dataf
}
}
df <- do.call(rbind, model)
df <- arrange(df, Country)
}
EC_Pop <- RowsToColums(EC_Pop)
EC_GDP <- RowsToColums(EC_GDP)
EC_Inflation <- RowsToColums(EC_Inflation)
ST_Tech_Exp <- RowsToColums(ST_Tech_Exp)
ST_Res_Jour <- RowsToColums(ST_Res_Jour)
ST_Res_Exp <- RowsToColums(ST_Res_Exp)
ST_Res_Pop <- RowsToColums(ST_Res_Pop)
ED_Unempl <- RowsToColums(ED_Unempl)
ED_Edu_Exp <- RowsToColums(ED_Edu_Exp)
But as you can see, I call many times the same function.
I tried to move all these dataframes in a vector like this
list_a = list(EC_Pop,EC_GDP,EC_Inflation,ST_Tech_Exp,ST_Res_Exp)
for (i in seq_along(list_a))
{
list_a[i] <- RowsToColums(list_a[i])
}
write a loop that everytime take the dataframe but it fails with an error
UseMethod ("arrange_") error:
Inapplicable method for 'arrange_' applied to object of class "NULL"
Does anybody know how to fix this case?

Related

Loop-generated list of data frames not being joined by rbind properly

I have a table with samples of data named Sample_1, Sample_2, etc. I take user input as a string for which samples are wanted (Sample_1,Sample_3,Sample_5). Then after parsing the string, I have a for-loop which I pass each sample name to and the program filters the original dataset for the name and creates a DF with calculations. I then append the DF to a list after each iteration of the loop and at the end, I rbind the list for a complete DF.
sampleloop <- function(samplenames) {
data <- unlist(strsplit(samplenames, ","))
temp = list()
for(inc in 1:length(data)) {
df <- CT[CT[["Sample_Name"]] == data[inc],]
........
tempdf = goitemp
temp[inc] <- tempdf
}
newdf <- do.call(rbind.data.frame, temp)
}
The inner function on its own produces the correct wanted output. However, with the loop the function produces the following wrong DF if the input is "Sample_3,Sample_9":
I'm wondering if it has something to do with the rbind?
The issue seems to be using [ instead of [[ to access and assign to the list element`
sampleloop <- function(samplenames) {
data <- unlist(strsplit(samplenames, ","))
temp <- vector('list', length(data))
for(inc in seq_along(data)) {
df <- CT[CT[["Sample_Name"]] == data[inc],]
........
tempdf <- goitemp
temp[[inc]] <- tempdf
}
newdf <- do.call(rbind.data.frame, temp)
return(newdf)
}
The difference can be noted with the reproducible example below
lst1 <- vector('list', 5)
lst2 <- vector('list', 5)
for(i in 1:5) {
lst1[i] <- data.frame(col1 = 1:5, col2 = 6:10)
lst2[[i]] <- data.frame(col1 = 1:5, col2 = 6:10)
}

How do I make dataframes in a for loop in R?

I want to create dataframes in a for loop where every dataframe gets a value specified in a vector. It seems very simple but for some reason I cannot find the answer.
So what I want is something like this:
x <- c(1,2,3)
for (i in x) {
df_{{i}} <- ""
return df_i
}
The result I want is:
df_1
df_2
df_3
So df_{{i}} should be something else but I don't know what.
EDIT: I have solved my problem by creating a list of lists like this:
function_that_creates_model_output <- function(var) {
output_function <- list()
output_function$a <- df_a %>% something(var)
output_function$b <- df_b %>% something(var)
return(output_function)
}
meta_output <- list()
for (i in x) {
meta_output[[i]] <- function_that_creates_model_output(var = i)
}
One solution would be to use the function assign
x <- c(1,2,3)
for (i in x) {
assign(x = paste0("df_",i),value = NULL)
}

Loop over a list in R

I want to do an operation if each data frame of a list. I want to perform the Kolmogorov–Smirnov (KS) test for one column in each data frame. I am using the code below but it is not working:
PDF_mean <- matrix(nrow = length(siteNumber), ncol = 4)
PDF_mean <- data.frame(PDF_mean)
names(PDF_mean) <- c("station","normal","gamma","gev")
listDF <- mget(ls(pattern="DSF_moments_"))
length(listDF)
i <- 1
for (i in length(listDF)) {
PDF_mean$station[i] <- siteNumber[i]
PDF_mean$normal[i] <- ks.test(list[i]$mean,"pnorm")$p.value
PDF_mean$gev[i] <- ks.test(list[i]$mean,"pgev")$p.value
PDF_mean$gamma[i] <- ks.test(list[i]$mean,"gamma")$p.value
}
Any help?
It is not length(listDF) instead, it would be seq_along(listDF) or 1:length(listDF) (however, it is more appropriate with seq_along) because length is a single value and it is not doing any loop
for(i in seq_along(listDF)) {
PDF_mean$station[i] <- listDF[[i]]$siteNumber
PDF_mean$normal[i] <- ks.test(listDF[[i]]$mean,"pnorm")$p.value
PDF_mean$gev[i] <- ks.test(listDF[[i]]$mean,"pgev")$p.value
PDF_mean$gamma[i] <- ks.test(listDF[[i]]$mean,"gamma")$p.value
}

Pass data frame by row to a function as a list

I'm trying to run a function over each row of a data frame using rowwise() and dplyr by passing each row as a list to the function and then using column names to access the variables.
The code below shows what I'm trying to do. The code passes the whole data frame to the function, it doesn't step through each row. Any suggestions please?
#initial dataframe
df <- data.frame(X=c(10,22,43,47,15), Y=c(2,3,4,2,2))
## cumbersome version - pass each variable
dfResult <- df %>%
rowwise() %>%
mutate(Z=FnAdd(X,Y)) %>%
mutate(K=FnMult(X,Y,Z))
FnAdd <- function(X,Y){
R <- c()
for(i in 1:4){
R[i]=X+i*Y
}
return (list(R))
}
FnMult <- function(X,Y,Z){
R <- c()
for(i in 1:4){
R[i]=X+i*Y*2*Z[i]
}
return (list(R))
}
##concise version - just pass a list of each row
#code runs but is incorrect - it always uses the first row
dfResultX <- df %>%
rowwise() %>%
mutate(Z=FnAddX(as.list(dfResult))) %>%
mutate(K=FnMultX(as.list(dfResult)))
#function should receive a list of one row
#actually receives list of whole data frame
FnAddX <- function(Vars){
R <- c()
for(i in 1:4){
R[i]=Vars$X+i*Vars$Y
}
return (list(R))
}
#ditto
debug(FnMultX)
FnMultX <- function(Vars){
R <- c()
for(i in 1:4){
V1 <- Vars$X
V2 <- Vars$Y
#next line of code is wrong and crashes function
V3 <- Vars$Z[1][i]
R[i]=Vars$X+i*Vars$Y*2*Vars$Z[i]
}
return (list(R))
}
#loop option
#not ideal but could work if dplyr won't
Result <- c()
for(i in 1:nrow(df)){
RowList <- as.list(df[i,])
NewVec <- FnAddX(RowList)
Result <- append(Result,NewVec)
}
#bind result to original data frame
#code not working - not sure how to do this
dfResultX <- df %>%
as.data.frame(Result)

For loop to eliminate columns in multiple dfs

I've got about 10 dataframes. For the example, here are two:
name <- c("A", "B", "C")
name.footnote <- c("this", "that", "the other")
class <- c("one", "two", "three")
class.footnote <- c("blank", "blank", "blank")
df1 <- data.frame(name, name.footnote, class, class.footnote)
df2 <- data.frame(name, name.footnote, class, class.footnote)
When I eliminate columns from them one at a time, my code works fine.
library(dplyr)
df1 <- select(df1, -ends_with("footnote"))
I'd like to write a loop to process both dfs with less code, but can't get my loop working right. I keep getting the same error message:
Error in UseMethod("select_") : no applicable method for 'select_'
applied to an object of class "character".
See a few of the many loop codes I've tried, below. What am I missing?
listofDfs <- list("df1","df2")
1.
lapply(listofDfs, function(df){
df <- select(df, -ends_with("footnote"))
return(df)
}
)
2.
for (i in listofDfs){
i <- select(i, -ends_with("footnote"))
}
Try dropping the quotes when defining your list listofDfs <- list(df1,df2). As the error states, when you have the quotes the elements of your list are character instead of the data.frame that select() is expecting.
library(dplyr)
listofDfs <- list(df1,df2)
#using lapply
list_out1 <- lapply(listofDfs, function(df){
df <- select(df, -ends_with("footnote"))
return(df)
})
#using for loop
list_out2 <- vector("list", length(listofDfs))
for (i in seq_along(listofDfs)){
list_out2[[i]] <- select(listofDfs[[i]], -ends_with("footnote"))
}
follow up per comment
you can use get and assign to work with your original character list and manipulate the dfs in your global environment while iterating.
listofDfs <- list('df1','df2')
invisible(lapply(listofDfs, function(i){
df <- select(get(i, globalenv()), -ends_with("footnote"))
assign(i, df, envir = globalenv())
}))
for (i in listofDfs){
df <- select(get(i, globalenv()), -ends_with("footnote"))
assign(i, df, envir = globalenv())
}

Resources