首页 > 解决方案 > 使用 purrr 更改每个列表(嵌套列表)的每个元素

问题描述

我对人口普查数据进行了数百次观察——每个特征都存储在一个名为 census 的列表中。我正在尝试执行一项操作

a) 在所有列表的所有元素上:我想将所有非字符元素设为数字。

b)每个列表中存在一个命名元素:我想从每个列表中的命名列中删除一个前缀

下面是一个玩具示例。

人口普查是列表中的嵌套列表

library(tidyverse)
library(purrr)


POA_CODE = c("POA101","POA102")
dogs = c(4,4) 
cats = c(3,2) 

children = c(0, 1)

salary = c(100, 120)
employed.prop = c(1,0.5)

pets <- list(POA_CODE, as.integer(dogs), as.integer(cats))

children <-list(POA_CODE, as.integer(children))

employment <-list(POA_CODE, salary, employed.prop)

census <- list(pets, children, employment)

尝试将每个列表中的所有非数字元素更改为数字

#change all non-numeric elements to numeric
census_num <- census %>% 
  map(function(x){
  ifelse(is.character == TRUE, x,
         as.numeric(x))}
  )

我收到以下错误消息:

Error in is.character == TRUE : 
  comparison (1) is possible only for atomic and list types 

尝试从 census[[]]$'POA_CODE' 中的每个邮政编码中删除前缀

#Remove "POA" prefix from every postcode
census_code <- pmap(census, ~.x[["POA_CODE"]],function(x){
  str_replace(POA_CODE,"POA","")
})

我得到错误

Error: Element 2 of `.l` must have length 1 or 3, not 2

标签: rpurrr

解决方案


你有一个嵌套列表,所以你需要嵌套maps :

library(purrr)
map(census, function(x) map_if(x, is.character, ~as.numeric(sub('POA', '', .x))))

#[[1]]
#[[1]][[1]]
#[1] 101 102

#[[1]][[2]]
#[1] 4 4

#[[1]][[3]]
#[1] 3 2


#[[2]]
#[[2]][[1]]
#[1] 101 102

#[[2]][[2]]
#[1] 0 1


#[[3]]
#[[3]][[1]]
#[1] 101 102

#[[3]][[2]]
#[1] 100 120

#[[3]][[3]]
#[1] 1.0 0.5

在基础 R 中,我们可以用嵌套解决它lapply

lapply(census, function(x) lapply(x, function(y) 
  if(is.character(y)) as.numeric(sub('POA', '', y)) else y))

推荐阅读