简体   繁体   中英

Iteratively assign variable names for calculations done on list within a list in R?

I have been having an issue in R studio for a while now and I would like to preface that I am still fairly new to R and still don't know all the "fastest" methods of doings things but any help and patience would be awesome.

I am a researcher having to calculate skill scores for weather models at different weather stations and have thousands of data points to iterate over and I figured the easiest method to do this was read in the files and store each file as a separate list in a list.

After doing this I would, loop over each list in the lists, and calculate different error scores (normal error, RMSE, etc...) saving me from having to copy and paste about 121 different loops. This method of doing things is clearly A) not a good method, or B) I do not have a firm grasp on the best way of doing this.

So, below is an quick example:

# The weather model forecasts
model1 <- c(1:15)
model2 <- c(1:15)
model3 <- c(1:15)

# What actually happened (verification/measured values)
verification_model1 <- c(1:15)
verification_model2 <- c(1:15)
verification_model3 <- c(1:15)

# List of lists containging total model data
totalmodeldata <- list(model1,model2,model3)
totalverificationdata <-list(verification_model1,verification_model2,verification_model3)

# Calculate normal error
for (val in totalmodeldata){
  for (ob in totalverificationdata){
    uniquevarname <- val - ob # here is the issue!
  }
}

So here is my one problem to make this a simple Q/A...

  1. Is there a simple method to assigning unique variable names for these individual lists within a list calculations? Because as it stands now, the code does what it's supposed to do with error calculations but only stores the last list it calculates (model3.

Ideally it would do something where it calculates normal error for model1 VS. verification_model1 assigns data to a variable then moves to the second lists and so on so that I have normal error for model1, model2, and model3.

UPDATE: Okay we are getting somewhere. This is the output I would like... After declaring the model data (model1..2..3, etc.) and verification data (verifcation_model1..2..3,etc.) into the "total" lists, a for loop or similar function would loop through and do the below subtraction to EACH model and verification data list:

unqiue_var_error1 <- model1 - verification_model1
unqiue_var_error2 <- model2 - verification_model2
unqiue_var_error3 <- model3 - verification_model3

The output/stored data would look like a simple vector of data for each model... Here is an actual output of normal error from my work:

> head(model1,n = 15L)
 [1] -6  0  1  0 -4 -2  2  0 -3 -2 -3 -5 -5 -5 -5

That way, once that loop is done I would have normal error for each model.

Here's a solution using a nested purrr::map2 .
(You don't really need the nested mapping, it just allows for wrapping the results in a single data frame.)

library(tidyverse)

map2_df(totalmodeldata, totalverificationdata,
     function(model, verify) {
       map2_dbl(model, verify, ~.x - .y)
     }
)

# A tibble: 10 x 3
   model1 model2 model3
    <dbl>  <dbl>  <dbl>
 1 -1.22  -0.611 -1.50 
 2  1.82   0.911  1.71 
 3  3.06   1.53   3.84 
 4 -1.40  -0.700 -1.37 
 5 -1.33  -0.665 -1.27 
 6  1.57   0.787  2.43 
 7  0.252  0.126  0.482
 8  1.77   0.886  1.14 
 9 -0.200 -0.100 -0.543
10  0.642  0.321  0.419

Data:

# added randomness to avoid having all zeros show up in diff scores

# The weather model forecasts
set.seed(123)
n <- 10
model1 <- rnorm(n)
model2 <- model1 * .5
model3 <- model1 * 1.5

# What actually happened (verification/measured values)
set.seed(234)
verification_model1 <- rnorm(n)
verification_model2 <- verification_model1 * .5
verification_model3 <- verification_model1 * 1.5

# List of lists containging total model data
totalmodeldata <- 
  list(model1, model2, model3) %>% set_names('model1', 'model2', 'model3')

totalverificationdata <-
  list(verification_model1, verification_model2, verification_model1) %>% 
  set_names('ver_model1', 'ver_model2', 'ver_model3')

Note: The purrr package is a tidyverse take on the base R apply family functions (and per OP comment, it is compatible with R >= 3.2).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM