当前位置: 首页 > 知识库问答 >
问题:

如何动态更改数据框中列的数据类型

潘俊
2023-03-14

我从中向R导入数据的平台不支持指定数据类型,因此我的所有列都是字符。我有一个Excel文件,指定哪些列是因子,包括相关的标签级别。现在,我正在尝试编写一个函数来动态更改数据中各个列的数据类型。框架

多亏了对这个问题的出色回答(dplyr-mutate:use dynamic variable names),我成功地编写了以下函数,在其中我动态地将列名设置为mutate函数。

readFactorData <- function(filepath) {
    t <- read.xlsx(filepath)
    sapply(nrow(t), function(i) {
      colname <- as.character(t[i, "Item"])
      factorLevels <- t[i, 3:ncol(t)][which(!is.na(t[i, 3:ncol(t)]))]
      totalLevels <- length(factorLevels)
      listOfLabels <- as.character(unlist(factorLevels))

      mutate(d, !!colname := factor(d[[colname]], labels=(1:totalLevels), levels=listOfLabels))
        # requires dplyr v.0.7+
        # the syntax `!!variablename:=` forces evaluation of the variablename before evaluating the rest of the function
    })
}

它起作用了,每次迭代都会返回整个数据帧,相关列(colname)更改为因子。但是,每次迭代都会覆盖之前的迭代,所以这个函数只返回i的最后一个结果。如何确保最终只有1个数据帧,其中保存了所有相关列?

示例数据(确保注释掉上面函数的第一行,因为我们在这里定义了t):

 d <- data.frame("id" = sample(100:999, 10), "age" = sample(18:80, 10), "factor1" = c(rep("a", 3), rep("b", 3), rep("c", 4)), "factor2" = c("x","y","y","y","y","x","x","x","x","y"), stringsAsFactors = FALSE)
 t <- data.frame("Item" = c("factor1","factor2"), "Label" = c("This is factor 1", "This is factor 2"), "level1" = c("a","x"), "level2" = c("b","y"), "level3" = c("c","NA"))

共有3个答案

童宏富
2023-03-14

下面的函数通过为要更改的每个命名列指定的readr::parse_*函数进行映射,然后允许您为每个列指定参数(例如,如果使用parse_factor,则级别)。

library(tidyverse)

parse_cols <- function(df, f, col_names, levels, ...){
  # df: dataframe, f: char vec, col_names: char vec, levels: list of char vecs,
  # ...: list of other potential args for parse_*
  params_t <- tibble(x = map(col_names, ~df[[.x]]), levels = levels, ...) %>% transpose()

  new_cols <- map2_df(.x = structure(f, names = col_names), 
                      .y = params_t, 
                      ~R.utils::doCall(.x, args = .y, .ignoreUnusedArgs = TRUE))  

  df[names(new_cols)] <- new_cols
  df
}

# function inputs -- perhaps just requiring a tibble input would be safer
parsings_vec <- c("parse_factor","parse_double", "parse_factor")
cols_vec <- c("manufacturer", "cty", "class")
factors_list <- list(unique(mpg[["manufacturer"]]), NULL, unique(mpg[["class"]]))

parse_cols(df = mpg, f = parsings_vec, col_names = cols_vec, levels = factors_list) 
#> # A tibble: 234 x 11
#>    manufacturer model displ  year   cyl trans drv     cty   hwy fl    cla~
#>    <fct>        <chr> <dbl> <int> <int> <chr> <chr> <dbl> <int> <chr> <fc>
#>  1 audi         a4      1.8  1999     4 auto~ f        18    29 p     com~
#>  2 audi         a4      1.8  1999     4 manu~ f        21    29 p     com~
#>  3 audi         a4      2    2008     4 manu~ f        20    31 p     com~
#>  4 audi         a4      2    2008     4 auto~ f        21    30 p     com~
#>  5 audi         a4      2.8  1999     6 auto~ f        16    26 p     com~
#>  6 audi         a4      2.8  1999     6 manu~ f        18    26 p     com~
#>  7 audi         a4      3.1  2008     6 auto~ f        18    27 p     com~
#>  8 audi         a4 q~   1.8  1999     4 manu~ 4        18    26 p     com~
#>  9 audi         a4 q~   1.8  1999     4 auto~ 4        16    25 p     com~
#> 10 audi         a4 q~   2    2008     4 manu~ 4        20    28 p     com~
#> # ... with 224 more rows
燕经国
2023-03-14

如果你想转换你所有的因素字符在你的data.frame你可以使用dplyrmutate_if。否则,如果你想使用列名的向量,@Eden Z的答案会帮你。

library(tidyverse)

d_out <- d %>% 
  mutate_if(is.character, as.factor)

d_out

#    id age factor1 factor2
#1  933  61       a       x
#2  208  52       a       y
#3  193  25       a       y
#4  231  47       b       y
#5  595  78       b       y
#6  675  28       b       x
#7  387  71       c       x
#8  386  80       c       x
#9  893  20       c       x
#10 272  23       c       y

当您可以检查类中的变量时:

sapply(d_out, class)

#       id       age   factor1   factor2 
#"integer" "integer"  "factor"  "factor" 
乜业
2023-03-14

如果我理解正确,你有一个数据帧,另一个数据帧的因子列值。你想从第一个df中提取这些,并在第二个df中变异这些列,并将它们转化为因子。

保留列名的向量,然后对它们进行变异怎么样?

colnames <- t %>%
  pull(Item) %>%
  as.character()

d_with_factors <- d %>%
  mutate_at(colnames, as.factor)

然后呢

sapply(d_with_factors, class)

返回

       id       age   factor1   factor2 
"integer" "integer"  "factor"  "factor" 
 类似资料:
  • 问题内容: 我正在尝试更改derby db列的数据类型。当前价格列设置为DECIMAL(5,0)。我想将其更改为DECIMAL(7,2)。我是这样做的: 但是它不起作用,并显示错误: 我可以知道如何进行更改吗?谢谢你。 问题答案: 这是Derby SQL脚本,用于将列MY_TABLE.MY_COLUMN从BLOB(255)更改为BLOB(2147483647):

  • 问题内容: 我想将多列的数据类型从float更改为int。最简单的方法是什么? 尚无数据可担心。 问题答案: http://dev.mysql.com/doc/refman/5.1/en/alter- table.html 这将更改给定列的数据类型 根据您希望修改的列数,最好生成一个脚本或使用某种mysql客户端GUI

  • 我现在正在开发一个系统,该系统将表的主键定义为“int”,这个主键有一个规则序列:“yearmonthmonth”6个数字。例如:“2105000001”,但“22”(2022)的年份没有被预测,或者,如果我将序列的这种模式调整到当前年份,它将给出一个错误,因为它超过了最大值。质疑:这个系统非常庞大,在java、postgresql数据库中,切换到Long的利弊是什么?它会对数据库性能产生类似的影

  • 问题内容: 我想将表示为列表列表的表转换为。作为一个极其简化的示例: 将列转换为适当类型的最佳方法是什么(在这种情况下,将列2和3转换为浮点数)?有没有一种方法可以在转换为DataFrame时指定类型?还是先创建DataFrame然后遍历各列以更改各列的类型更好?理想情况下,我想以动态方式执行此操作,因为可以有数百个列,并且我不想确切指定哪些列属于哪种类型。我可以保证的是,每一列都包含相同类型的值

  • 问题内容: 我有一个Spring应用程序,我想动态更改数据源。当输入DS URL时,Spring Bean和所有依赖项将自动更新。我知道这有些奇怪,但是无论如何我都想实现。我的Spring配置如下: 问题是: JDBC URL存储在属性中,可以在运行时更改它。 更改URL后,我需要重新创建数据源,可能还需要重新创建相关对象。我不知道Spring如何优雅地做呢? 我知道Spring确实可以基于一个键

  • 我有一个Spring应用程序,我想动态更改数据源,即。当输入DS URL时,Spring bean和所有依赖项将自动更新。我知道这有点奇怪,但无论如何我想实现这一点。我的Spring配置如下: 问题是: > 一旦URL被更改,我需要重新创建数据源,可能还有依赖对象。我不知道如何在Spring优雅地做这件事? 我知道Spring可以基于一个键动态路由数据源,但数据源URL是在Spring中预定义的,