正确地将列表子集替换为元素值

时间:2018-10-02 17:10:19

标签: r list

上下文:
我有一个数据框列表,每个数据框包含不同的维度和列数据类型。我的最终目标是创建一个包含列名和数据类型的命名向量,我可以使用该向量显式分配用于将表写入数据库的字段类型-field.types DBI::dbWriteTable()参数>

方法:
我当前的方法是使用class提取列表中列的数据类型,并对其进行修改,以便可以将其用作field.types参数中的命名向量。我需要评估数据是否是真正的整数值,并基于this SO post编写了一个函数来完成该操作。

目标
我想使用自己函数的列表输出来识别和修改命名向量中真正为整数值的数据类型。

问题:
我想用逻辑向量替换基于另一个列表list_class的列表list_int中的元素。我可以对单个数据帧进行这种简单的替换/分配,但是在使用数据帧列表时遇到了子集问题。我在下面提供了一个可复制的示例,并对此进行了一些尝试。

library(purrr)

list_df <- list(
  df1 = data.frame(v1 = seq(1,10,2),
                   v2 = seq(1,5,1),
                   v3 = seq(1,10,length.out = 5)),
  df2 = data.frame(v2 = c(seq(1,5), NA),
                   v3 = seq(2,7,1),
                   v4 = rep(pi,6)),
  df3 = data.frame(v3 = seq(1,2,length.out = 5),
                   v4 = sample(letters,5),
                   v5 = seq(1,10,2),
                   v6 = seq(1,5,1))
  )

list_class <- map(list_df, ~map_chr(., class)) #named vector

check_int <- function(v) { #check if truly integer value
  if (!is.numeric(v)) FALSE
  else all((v%%1 == 0)[!is.na(v%%1 == 0)])
}

list_int <- map(list_df, ~map_lgl(., ~check_int(.)))

对于下面的单个数据框有效

list_class[[1]][list_int[[1]]] <- "newdatatype"

并且我能够使用基础Map从列表中提取想要的子集。

Map('[', list_class, list_int)

是否想了解如何将所有这些部分放在一起,或者我的方法是否完全不可行?

2 个答案:

答案 0 :(得分:3)

一个简单的for循环应该可以工作,但是如果您想使用map2解决方案,也可以使用purrr

用于循环:

for(i in seq_along(list_class))
  list_class[[i]][list_int[[i]]] <- "newdatatype"

purrr:

map2(list_class, list_int, ~{.x[.y] <- 'newdatatype'; .x})

输出:

# $df1
#            v1            v2            v3 
# "newdatatype" "newdatatype"     "numeric" 
# 
# $df2
#            v2            v3            v4 
# "newdatatype" "newdatatype"     "numeric" 
# 
# $df3
#            v3            v4            v5            v6 
#     "numeric"      "factor" "newdatatype" "newdatatype" 

答案 1 :(得分:3)

你可以做...

Map(replace, list_class, list_int, "newdatatatype")
# or
Map(function(x, p) replace(x, p, "newdatatatype"), list_class, list_int)

这会创建一个新对象,而不是修改list_class,但是您使用的是tidyverse,因此我想无论如何都不会对修改输入感兴趣。如果您真的想要,有...

library(magrittr)
list_class %<>% Map(
  f = function(x, p) replace(x, p, "newdatatatype"), 
  p = list_int
)

旁注:如果您查看replace中的代码,您会发现它只是Ryan的代码更直接执行的包装器/便捷函数。