应用嵌套列表名称:嵌套列表名称中的子输出字符

时间:2018-01-20 13:54:26

标签: r list recursion

我有未知结构(嵌套)的列表,它总是以命名向量终止。我想用列表中的所有句点或原子向量名替换下划线。有rapply将functios应用于列表元素,但如何应用列表/原子向量的名称?我是基于R的解决方案,但请为其他人分享所有解决方案。

MWE

x <- list(
    urban = list(
        cars = c('volvo', 'ford'),
        food.dining = list(
            local.business = c('carls'),
            chain.business = c('dennys', 'panera')
        )
    ),
    rural = list(
        land.use = list(
            farming =list(
                dairy = c('cows'),
                vegie.plan = c('carrots')
            )
        ),
        social.rec = list(
            community.center = c('town.square')
        ),
        people.type = c('good', 'bad', 'in.between')
    ),
    other.locales = c('suburban'),
    missing = list(
        unknown = c(),
        known = c()
    ),
    end = c('wow')
)

期望的结果

## $urban
## $urban$cars
## [1] "volvo" "ford" 
## 
## $urban$food_dining
## $urban$food_dining$local_business
## [1] "carls"
## 
## $urban$food_dining$chain_business
## [1] "dennys" "panera"
## 
## 
## 
## $rural
## $rural$land_use
## $rural$land_use$farming
## $rural$land_use$farming$dairy
## [1] "cows"
## 
## $rural$land_use$farming$vegie_plan
## [1] "carrots"
## 
## 
## 
## $rural$social_rec
## $rural$social_rec$community_center
## [1] "town.square"
## 
## 
## $rural$people_type
## [1] "good"       "bad"        "in.between"
## 
## 
## $other_locales
## [1] "suburban"
## 
## $missing
## $missing$unknown
## NULL
## 
## $missing$known
## NULL
## 
## 
## $end
## [1] "wow"

3 个答案:

答案 0 :(得分:5)

这是一个递归函数的想法。它首先用下划线替换名称中的句点。然后检查元素的类是否为list,如果是,则将该函数应用于该元素。否则,如果类为character,则它将元素中的句点替换为下划线。请注意,如果列表中有data.frames,那么这将不起作用,它必须是函数中定义的扩展名。希望这有帮助!

功能:

my_func <- function(x)
{
    names(x) <- gsub('\\.','_',names(x) )
    for(i in 1:length(x))
    {
      if(any(class(x[[i]])=='list'))
      {
        x[[i]] <- my_func(x[[i]])
      }
    }
    return(x)
}
y <- my_func(x)

数据:

x <- list(
  urban = list(
    cars = c('volvo', 'ford'),
    food.dining = list(
      local.business = c('carls'),
      chain.business = c('dennys', 'panera')
    )
  ),
  rural = list(
    land.use = list(
      farming =list(
        dairy = c('cows'),
        vegie.plan = c('carrots')
      )
    ),
    social.rec = list(
      community.center = c('town.square')
    ),
    people.type = c('good', 'bad', 'in.between')
  ),
  other.locales = c('suburban'),
  missing = list(
    unknown = c(),
    known = c()
  ),
  end = c('wow')
)

输出:

 str(y)

List of 5
 $ urban        :List of 2
  ..$ cars       : chr [1:2] "volvo" "ford"
  ..$ food_dining:List of 2
  .. ..$ local_business: chr "carls"
  .. ..$ chain_business: chr [1:2] "dennys" "panera"
 $ rural        :List of 3
  ..$ land_use   :List of 1
  .. ..$ farming:List of 2
  .. .. ..$ dairy     : chr "cows"
  .. .. ..$ vegie_plan: chr "carrots"
  ..$ social_rec :List of 1
  .. ..$ community_center: chr "town.square"
  ..$ people_type: chr [1:3] "good" "bad" "in.between"
 $ other_locales: chr "suburban"
 $ missing      :List of 2
  ..$ unknown: NULL
  ..$ known  : NULL
 $ end          : chr "wow"

答案 1 :(得分:4)

对于list个对象,它将重命名list并递归地为每个元素调用相同的函数。对于character个对象,它只会返回character

library('purrr')

fix_names.list <- function(v) {
  names(v) <- gsub('\\.', '_', names(v))
  map(v, fix_names)
}

fix_names.default <- function(v) v

fix_names <- function(v) UseMethod('fix_names')

fix_names(x) %>% str
 # List of 5
 # $ urban        :List of 2
 #  ..$ cars       : chr [1:2] "volvo" "ford"
 #  ..$ food_dining:List of 2
 #  .. ..$ local_business: chr "carls"
 #  .. ..$ chain_business: chr [1:2] "dennys" "panera"
 # $ rural        :List of 3
 #  ..$ land_use   :List of 1
 #  .. ..$ farming:List of 2
 #  .. .. ..$ dairy     : chr "cows"
 #  .. .. ..$ vegie_plan: chr "carrots"
 #  ..$ social_rec :List of 1
 #  .. ..$ community_center: chr "town.square"
 #  ..$ people_type: chr [1:3] "good" "bad" "in.between"
 # $ other_locales: chr "suburban"
 # $ missing      :List of 2
 #  ..$ unknown: NULL
 #  ..$ known  : NULL
 # $ end          : chr "wow"

答案 2 :(得分:1)

这不是base-R的方法,但可能仍然很重要,因为可以使用rrapply包中的rrapply开箱即用(base-{{的扩展名) 1}}):

rapply
library(rrapply) res1 <- rrapply(list(x), f = function(x) { names(x) <- gsub("\\.", "_", names(x)); x }, classes = "list", how = "recurse")[[1]] str(res1) #> List of 5 #> $ urban :List of 2 #> ..$ cars : chr [1:2] "volvo" "ford" #> ..$ food_dining:List of 2 #> .. ..$ local_business: chr "carls" #> .. ..$ chain_business: chr [1:2] "dennys" "panera" #> $ rural :List of 3 #> ..$ land_use :List of 1 #> .. ..$ farming:List of 2 #> .. .. ..$ dairy : chr "cows" #> .. .. ..$ vegie_plan: chr "carrots" #> ..$ social_rec :List of 1 #> .. ..$ community_center: chr "town.square" #> ..$ people_type: chr [1:3] "good" "bad" "in.between" #> $ other_locales: chr "suburban" #> $ missing :List of 2 #> ..$ unknown: NULL #> ..$ known : NULL #> $ end : chr "wow" 应用到类型how = "recurse"的每个元素后,

f继续递归。在这里,我将输入对象包装为classes = "list",以便也在顶部列表层应用list(x)函数,而不是从其列表元素开始。


注意:我们可以轻松地更新调用以在名称​​和嵌套列表的值中组合替换:

f