【问题标题】:Change data types using a list of data type names使用数据类型名称列表更改数据类型
【发布时间】:2019-11-08 10:21:53
【问题描述】:

从数据类型名称列表中更改数据框列的数据类型的优雅方法是什么?

这是一个示例(我正在寻找 change_to_data_types 函数):

my_df <- iris
my_types <- c("factor", "character", "double", "logical", "character")
my_df <- my_df %>% change_to_data_types(my_types)

my_types 的元素个数与my_df 中的列数相同,并且转换的顺序相同。

这是一个“不雅”方式的例子

my_df$Sepal.Length <- my_df$Sepal.Length %>% as.factor()
my_df$Sepal.Width <- my_df$Sepal.Width %>% as.character()
#etc...

【问题讨论】:

  • 只是一个疑问,在阅读数据本身时这样做会不会更好,即在阅读时colClasses 中有更简单的选项
  • 可能在读入数据时定义 colClasses?比如:mydf &lt;- read.table(..., colClasses = c("factor", "character", "double", "logical", "character")
  • 在拆分包含混合数据类型的较大表后,数据框位于列表中。
  • 这可能会变成“XY 问题”,为什么不确保列表是由相同的数据帧结构创建的呢?
  • 拆分是由原始数据帧中的一列完成的,该列是所有数据帧共有的唯一列。我不控制原始数据框或结构。

标签: r dataframe dplyr data.table


【解决方案1】:

我们可以使用mapply 提供utils::as 对列和类型。这不适用于因子列,因此将单独处理。

fcols <- my_types == "factor"
my_df[!fcols] <- mapply(as, my_df[!fcols], my_types[!fcols], SIMPLIFY = FALSE)
my_df[fcols] <- lapply(my_df[fcols], factor)

【讨论】:

  • 为什么不在一个 lapply() 调用中完成呢?
  • @sindri_baldur 个人品味,真的。我发现这比使用 if/else 逻辑为单个 mapply 创建函数更容易阅读。您的里程可能会有所不同。
【解决方案2】:

编辑: 为了避免由于数字直接转换为因子而导致格式错误,我们可以这样做:

lapply(seq_along(names(my_df)),
                 function(x){
                   if(is.numeric(my_df[,x]) &
                      my_types[x] =="factor"){
                    as.factor(as.character(my_df[,x]))
                   } 
                   else{
                     as(my_df[,x],my_types[x])
                   }
                 }
                   )

原创

我们可以做到:

sapply(seq_along(names(my_df)),
       function(x)  as(my_df[,x],my_types[x]))

【讨论】:

  • 我发现它很难与 map2 一起使用,形成了畸形因子。
  • 这会返回一个矩阵,这意味着所有列都属于同一类。
  • 我认为您需要将 sapply 更改为 lapply 并分配回输出
  • 应该像my_df[] &lt;- lapply(seq_along(my_df), function(x) as(my_df[[x]], my_types[x]))
  • @IceCreamToucan 已编辑,您对编辑的意见将不胜感激。
【解决方案3】:

match.fun

my_df[] <- lapply(seq_along(names(my_df)),
                  function(i) match.fun(paste0("as.", my_types[ i ]))(my_df[[ i ]]))


sapply(my_df, class)
# Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
#     "factor"  "character"    "numeric"    "logical"  "character" 

【讨论】:

    【解决方案4】:

    一个选项是

    library(tidyverse)
    my_df[] <- map2(my_df, str_c("as.", my_types), ~ get(.y)(.x))
    

    或在base R

    my_df[] <- Map(function(x, y) get(y)(x), my_df, paste0("as.", my_types))
    

    -再次检查课程

    sapply(my_df, class)
    # Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
    #    "factor"  "character"    "numeric"    "logical"  "character" 
    

    【讨论】:

    • 哇,get() 怎么了?它从字符串中获取函数并将第二个括号中的对象作为所述函数的输入?以前没见过。
    • @Humpelstielzchen 它返回函数值,() 是该函数的输入。这里是as.factor(column)
    猜你喜欢
    • 2014-03-05
    • 2016-12-21
    • 1970-01-01
    • 2013-09-12
    • 2014-01-20
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多