R: for-loop или lapply для некоторых элементов именованного списка - PullRequest
2 голосов
/ 06 января 2020

Например, у меня есть файл config.R с параметрами модели, который выглядит следующим образом:

var1 = "Fruit"
var2 = "Vegetables"
country = c("BRAZIL", "ECUADOR", "Georgia")
flag = NULL
peak = 30
years = c(2010, 2020)
remove1 = c("Bananas_ZZ_100s", "Apple_150-300_Pk", "Mango_mono")
remove2 = c("Tomato_ZR_400s", "cabbage300_Pk")

Затем я загружаю файл конфигурации:

params = new.env()
source("config/config.R", params)
params = mget(ls(params), envir = params)

и получаю именованный список с параметрами:

> print(params)

$var1 
[1] "Fruit"

$var2 
[1] "Vegetables"

$country
[1] "BRAZIL"    "ECUADOR"    "Georgia" 

et c.

Я хочу преобразовать символьные переменные в моем списке параметров в нижний регистр, за исключением двух переменных: remove1 и remove2

Мне удалось преобразовать все символьные переменные в списке следующим образом:

  params = lapply(params, function(params) {
  if (is.character(params)) return(tolower(params))
  else return(params)
  })

, но я не знаю, как применить эту функцию (или может быть с for петлями) для всех символов var. исключая несколько переменных.

Буду очень признателен за любую помощь!

PS что я хочу получить:

> print(params)

$var1 
[1] "fruit"

$var2 
[1] "vegetables"

$country
[1] "brazil"  "ecuador"  "georgia" 

$flag
NULL

$peak
[1] 30

$years
[1] 2010   2020

$remove1
[1] "Bananas_ZZ_100s"   "Apple_150-300_Pk"   "Mango_mono"

$remove2
[1] "Tomato_ZR_400s"   "cabbage300_Pk"

Ответы [ 2 ]

3 голосов
/ 06 января 2020

Поскольку вам нужны и имена, и значения в списке, мы можем использовать Map

Map(function(x, y) if(is.character(x) & !y %in% c('remove1', 'remove2'))
                   tolower(x) else x, params, names(params))


#country
#[1] "brazil"  "ecuador" "georgia"

#$flag
#NULL

#$peak
#[1] 30

#$remove1
#[1] "Bananas_ZZ_100s"  "Apple_150-300_Pk" "Mango_mono"      

#$remove2
#[1] "Tomato_ZR_400s" "cabbage300_Pk" 

#$var1
#[1] "fruit"

#$var2
#[1] "vegetables"

#$years
#[1] 2010 2020

Это может быть проще с purrr::imap

purrr::imap(params, ~if(is.character(.x) & !.y %in% c('remove1', 'remove2'))  
                     tolower(.x) else .x)

Вы можете также сначала найдите элементы, которые нам нужно изменить, а затем примените к ним tolower.

inds <- !names(params) %in% c('remove1', 'remove2') & sapply(params, is.character)
params[inds] <- lapply(params[inds], tolower)
0 голосов
/ 06 января 2020

Другой вариант, если это поможет?

params <- list(
  var1 = "Fruit",
  var2 = "Vegetables",
  country = c("BRAZIL", "ECUADOR", "Georgia"),
  flag = NULL,
  peak = 30,
  years = c(2010, 2020),
  remove1 = c("Bananas_ZZ_100s", "Apple_150-300_Pk", "Mango_mono"),
  remove2 = c("Tomato_ZR_400s", "cabbage300_Pk"))

# list of params to exclude from tolower check
exclude <- alist(remove1=, remove2=)

# create an unnamed list with the correct params lowered
params.lower <- lapply(names(params), function (name) {

  # if the name of the param is not in the exculsion list and the value is character
  if (!name %in% names(exclude) && is.character(params[[name]])) {

    # return the lower case value of the param
    tolower(params[[name]]) 

  } else { 

    # return the value of the param unchanged
    params[[name]]
  }
})

# assign the param names to the new list
names(params.lower) <- names(params)

params.lower
#$var1
#[1] "fruit"

#$var2
#[1] "vegetables"

#$country
#[1] "brazil"  "ecuador" "georgia"

#$flag
#NULL

#$peak
#[1] 30

#$years
#[1] 2010 2020

#$remove1
#[1] "Bananas_ZZ_100s"  "Apple_150-300_Pk" "Mango_mono"      

#$remove2
#[1] "Tomato_ZR_400s" "cabbage300_Pk" 

...