如何使用r purrr:map创建多个相同的对象(例如数据框)

时间:2018-08-08 13:47:49

标签: r purrr

我想知道在一般情况下可以使用purrr的映射函数创建对象的程度,尽管目前和下面的示例中我正在研究数据帧。

A<-seq(1:5)
B<-seq(6:10)
C<-c("x","y","x","y","x")
dat<data.frame(A,B,C)
cols<-names(dat)

create_df<-function(x) {
    x<- dat[x]
    return(x)
}
A<-create_df("A")

这将创建一个名为A的数据框,其数据来自dat。我想创建数据框架A / B / C,每个框架只有一列。我尝试了不同的方法来指定.f参数以及不同的地图函数(map,map2,map_dfc等)。我最初的最佳猜测:

map(.x=cols,~create_df(.x))    

说明:我寻求帮助,因为我尝试过的所有地图规范都给出了错误。

有效的代码:

map(names(dat), ~assign(.x, dat[.x], envir = .GlobalEnv))

这将A / B / C创建为数据帧并打印到控制台(我不需要,但暂时不打扰我)。

2 个答案:

答案 0 :(得分:2)

我们可以使用split中的base R来获得list的一列data.frame s

lst <- split.default(dat, names(dat))

最好将其保留在list中,但是如果要在全局环境中具有多个对象

list2env(lst, envir = .GlobalEnv)

答案 1 :(得分:1)

我认为使用purrr包是不必要的。 该功能包括对数据的引用,该引用不是最佳的(尤其是在环境中不存在的情况下)。

以单列数据帧的列表形式返回:

cols<-names(dat)
map(cols, ~dat[.x])

或者:map(names(dat), ~dat[.x])

返回:

[[1]]
# A tibble: 5 x 1
      A
  <int>
1     1
2     2
3     3
4     4
5     5

[[2]]
# A tibble: 5 x 1
      B
  <int>
1     1
2     2
3     3
4     4
5     5

[[3]]
# A tibble: 5 x 1
  C    
  <chr>
1 x    
2 y    
3 x    
4 y    
5 x    

如果您要遵守tidyverse原则,则可以将它们存储在数据框中作为列表列。

dfs <-
  data_frame(column = cols) %>% 
    mutate(data = map(cols, ~dat[.x]))

# A tibble: 3 x 2
  column data            
  <chr>  <list>          
1 A      <tibble [5 x 1]>
2 B      <tibble [5 x 1]>
3 C      <tibble [5 x 1]>

您可以根据需要提取单个数据:

B <- dfs$data[[2]]  

# A tibble: 5 x 1
      B
  <int>
1     1
2     2
3     3
4     4
5     5

沿着您原始建议的内容,这是一个在其中使用purrr:map的替代功能。我不确定这是一个好主意,但也许有用:

create_objects_from_df <- function(dat) {
  map(names(dat), ~assign(.x, dat[.x], envir = .GlobalEnv))
  }
create_objects_from_df(dat)

这将在全局环境中创建对象,将其作为具有列名称的单个对象。